home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Applications / NIH Image 1.60 / 1.60 Source / Image.p < prev    next >
Encoding:
Text File  |  1996-03-11  |  72.8 KB  |  2,831 lines  |  [TEXT/PJMM]

  1. program Image;
  2.  
  3. {NIH Image is a public domain program for the Macintosh for acquiring, }
  4. {processing, analyzing, editing, printing, and animating 8-bit images.}
  5.  
  6.  
  7. {Version 1.60, 2 Feb 1996}
  8.  
  9.  
  10. {Developed using Metrowerks CodeWarrior CW8 PPC and 68K Pascal compilers.}
  11.  
  12. {Author :}
  13. {Wayne Rasband}
  14. {National Institutes of Health}
  15.  
  16. {email: wayne@helix.nih.gov}
  17. {WWW: http://rsb.info.nih.gov/nih-image/}
  18. {Anonymous FTP: zippy.nimh.nih.gov}
  19. {Phone: 301-496-4957}
  20.  
  21.  
  22.     uses
  23.         Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, 
  24.         Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows, OSUtils,
  25.         Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, Processes,
  26.         Devices, Balloons, AppleEvents, DiskInit, EPPC, SegLoad,
  27.         Globals, Utilities, Init, File1, File2, Analysis, Graphics, 
  28.         Edit, Filters, Camera, User, Macros1, Macros2, Stacks, Background,
  29.         Lut, Projection, Plugins, Text, Math, Registration, {Profiler,} fft;
  30.  
  31.  
  32. {Turn off automatic toolbox initialization.}
  33. {$I-}
  34.  
  35.  
  36. {PROCEDURE MacsBug; inline $a9ff;}
  37.  
  38.  
  39.     procedure UpdateOptionsMenu;
  40.         var
  41.             CheckIt: boolean;
  42.             i: integer;
  43.     begin
  44.         with info^ do begin
  45.                 CheckItem(OptionsMenuH, GrayscaleItem, (LutMode = Grayscale) or (LutMode = CustomGrayscale));
  46.                 if LutMode <> PseudoColor then
  47.                     ColorTable := CustomTable;
  48.                 CheckItem(ColorTablesMenuH, SystemPaletteItem, ColorTable = AppleDefault);
  49.                 CheckItem(ColorTablesMenuH, Pseudo20Item, ColorTable = Pseudo20);
  50.                 CheckItem(ColorTablesMenuH, Pseudo32Item, ColorTable = Pseudo32);
  51.                 CheckItem(ColorTablesMenuH, RainbowItem, ColorTable = Rainbow);
  52.                 CheckItem(ColorTablesMenuH, Fire1Item, ColorTable = Fire1);
  53.                 CheckItem(ColorTablesMenuH, Fire2Item, ColorTable = Fire2);
  54.                 CheckItem(ColorTablesMenuH, IceItem, ColorTable = Ice);
  55.                 CheckItem(ColorTablesMenuH, GraysItem, ColorTable = Grays);
  56.                 CheckItem(ColorTablesMenuH, SpectrumItem, ColorTable = Spectrum);
  57.                 SetMenuItem(OptionsMenuH, ScaleToFitItem, info <> NoInfo);
  58.                 CheckIt := ScaleToFitWindow;
  59.                 CheckItem(OptionsMenuH, ScaleToFitItem, CheckIt);
  60.                 CheckItem(OptionsMenuH, ThresholdItem, Thresholding);
  61.                 CheckItem(OptionsMenuH, SliceItem, DensitySlicing);
  62.                 SetMenuItem(OptionsMenuH, PropagateItem, nPics > 1);
  63.             end;
  64.     end;
  65.  
  66.  
  67.     procedure UpdateProcessMenu;
  68.         var
  69.             ShowItems: boolean;
  70.             i: integer;
  71.             str: str255;
  72.     begin
  73.         ShowItems := Info <> NoInfo;
  74.         for i := SmoothItem to FilterItem do
  75.             SetMenuItem(ProcessMenuH, i, ShowItems);
  76.         with info^ do
  77.             if (LutMode = GrayScale) or (LutMode = CustomGrayscale) or DensitySlicing then
  78.                 SetMenuItemText(ProcessMenuH, ApplyItem, 'Apply LUT')
  79.             else
  80.                 SetMenuItemText(ProcessMenuH, ApplyItem, 'Convert to Grayscale');
  81.         if CurrentWindow = TextKind then
  82.             SetMenuItemText(ProcessMenuH, ConvolveItem, 'Convolve')
  83.         else
  84.             SetMenuItemText(ProcessMenuH, ConvolveItem, 'Convolve…');
  85.         for i := BinaryItem to FixColorsItem do
  86.             SetMenuItem(ProcessMenuH, i, ShowItems);
  87.         NumToString(BinaryCount, str);
  88.         str := concat('Set Count[', str, ']…');
  89.         SetMenuItemText(BinaryMenuH, SetCountItem, str);
  90.         NumToString(BinaryIterations, str);
  91.         str := concat('Set Iterations[', str, ']…');
  92.         SetMenuItemText(BinaryMenuH, IterationsItem, str);
  93.         CheckItem(BackgroundMenuH, FasterItem, FasterBackgroundSubtraction);
  94.         NumToString(BallRadius, str);
  95.         str := concat('Set Radius[', str, ']…');
  96.         SetMenuItemText(BackgroundMenuH, RadiusItem, str);
  97.     end;
  98.  
  99.  
  100.  
  101.  
  102.     procedure UpdateSpecialMenu;
  103.         var
  104.             ShowItems: boolean;
  105.     begin
  106.         ShowItems := Info <> NoInfo;
  107.         SetMenuItem(SpecialMenuH, SaveBlankFieldItem, ShowItems);
  108.         SetMenuItem(SpecialMenuH, PhotoModeItem, ShowItems);
  109.         if CurrentWindow = TextKind then
  110.             SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load Macros from Window')
  111.         else
  112.             SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load Macros…')
  113.     end;
  114.  
  115.  
  116.     procedure UpdateStacksMenu;
  117.         var
  118.             ShowItems: boolean;
  119.             isStack: boolean;
  120.     begin
  121.         ShowItems := Info <> NoInfo;
  122.         SetMenuItem(StacksMenuH, StackFromWindowsItem, nPics > 0);
  123.         isStack := info^.StackInfo <> nil;
  124.         SetMenuItem(StacksMenuH, WindowsFromStackItem, isStack);
  125.         SetMenuItem(StacksMenuH, AddSliceItem, isStack);
  126.         SetMenuItem(StacksMenuH, DeleteSliceItem, isStack);
  127.         SetMenuItem(StacksMenuH, NextSliceItem, isStack);
  128.         SetMenuItem(StacksMenuH, PreviousSliceItem, isStack);
  129.         SetMenuItem(StacksMenuH, MakeMovieItem, ShowItems);
  130.         SetMenuItem(StacksMenuH, CaptureFramesItem, ShowItems);
  131.         SetMenuItem(StacksMenuH, AnimateItem, isStack);
  132.         SetMenuItem(StacksMenuH, AverageSlicesItem, isStack);
  133.         SetMenuItem(StacksMenuH, MakeMontageItem, isStack);
  134.         SetMenuItem(StacksMenuH, RegisterItem, isStack);
  135.         SetMenuItem(StacksMenuH, CaptureColorItem, ShowItems);
  136.         SetMenuItem(StacksMenuH, RGBToColorItem, isStack);
  137.         SetMenuItem(StacksMenuH, ColorToRGBItem, ShowItems and (not isStack));
  138.         SetMenuItem(StacksMenuH, RGBToHSVItem, isStack);
  139.         SetMenuItem(StacksMenuH, ProjectItem, isStack);
  140.         SetMenuItem(StacksMenuH, ResliceItem, isStack);
  141.         SetMenuItem(StacksMenuH, StackInfoItem, isStack);
  142.     end;
  143.  
  144.  
  145.     function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean;
  146. { simple filter proc for about box -- must be at top level! % }
  147.     begin
  148.         if (event.what in [MouseDown, KeyDown, AutoKey]) then begin
  149.                 AboutFilter := true;
  150.                 ItemHit := OK;
  151.             end
  152.         else begin
  153.                 AboutFilter := false;
  154.                 ItemHit := 0;
  155.             end;
  156.     end;
  157.  
  158.  
  159.     procedure AboutUProc (d: DialogPtr; item: integer);
  160. { About box user proc -- must be at top level!}
  161.         var
  162.             s: str255;
  163.             saveport: grafptr;
  164.             VersInfo: str255;
  165.     begin
  166.         getport(saveport);
  167.         setport(d);
  168.         if (item = MemItem) then begin
  169.                 NumToString(FreeMem div 1024, s);
  170.                 s := concat(s, 'K free');
  171.                 DrawSItem(MemItem, Geneva, 9, d, s);
  172.             end
  173.         else if (item = VersItem) then begin
  174.                 RealToString(version / 100.0, 4, 2, VersInfo);
  175.                 VersInfo := concat('Version ', VersInfo);
  176.                 DrawSItem(VersItem, Geneva, 9, d, VersInfo);
  177.             end;
  178.         setport(saveport);
  179.     end;
  180.  
  181.  
  182.     procedure DoAbout;
  183.   {About Box by David Powell}
  184.         var
  185.             i: integer;
  186.             d: dialogptr;
  187.             midscreen: point;
  188.             r: rect;
  189.             h: handle;
  190.             itype: integer;
  191.     begin
  192.         if AboutBoxFilterProc=nil
  193.             then AboutBoxFilterProc:=NewRoutineDescriptor(@AboutFilter, uppModalFilterProcInfo, GetCurrentISA);
  194.         if AboutBoxUserProc=nil
  195.             then AboutBoxUserProc:=NewRoutineDescriptor(@AboutUProc, uppUserItemProcInfo, GetCurrentISA);
  196.         d := getnewdialog(AboutID, nil, pointer(-1));
  197.         if (d <> nil) then begin
  198.                 SetPort(d);
  199.                 GetDialogItem(d, VersItem, itype, h, r);
  200.                 SetDialogItem(d, VersItem, itype, handle(AboutBoxUserProc), r);
  201.                 GetDialogItem(d, MemItem, itype, h, r);
  202.                 SetDialogItem(d, MemItem, itype, handle(AboutBoxUserProc), r);
  203.                 ShowWindow(d);
  204.                 repeat
  205.                     ModalDialog(AboutBoxFilterProc, i);
  206.                 until (i = OK);
  207.                 DisposeDialog(d);
  208.                 FlushEvents(EveryEvent, 0);
  209.             end;
  210.     end;
  211.  
  212.  
  213.     procedure DoPreferences;
  214.         const
  215.             BufferSizeID = 4;
  216.             ScaleConvolutionsID = 6;
  217.             InvertValuesID = 7;
  218.             InvertYID = 8;
  219.             SwitchingID = 9;
  220.             HighlightID = 10;
  221.             CreatorID = 12;
  222.             OscillatingID = 14;
  223.             FriendlyID = 15;
  224.         var
  225.             mylog: DialogPtr;
  226.             item, i: integer;
  227.             SaveScaleC: boolean;
  228.             SaveInvertValues, SaveInvertY, SaveMovies, NewFriendlyMode, okay: boolean;
  229.             SaveBufferSize: LongInt;
  230.             SaveCreator: packed array[1..4] of char;
  231.             tCreator:str255;
  232.             SaveInfo:InfoPtr;
  233.     begin
  234.         InitCursor;
  235.         if isInvertingFunction then
  236.             InvertPixelValues:=true;
  237.         SaveBufferSize := BufferSize;
  238.         SaveInvertY := InvertYCoordinates;
  239.         SaveScaleC := ScaleConvolutions;
  240.         SaveCreator := TextCreator;
  241.         SaveMovies := OscillatingMovies;
  242.         NewfriendlyMode := LutFriendlyMode;
  243.         mylog := GetNewDialog(6000, nil, pointer(-1));
  244.         SetDNum(MyLog, BufferSizeID, BufferSize div 1024);
  245.         SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  246.         SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates));
  247.         SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  248.         SetDlogItem(mylog, HighlightID, ord(HighlightMode));
  249.         SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies));
  250.         SetDlogItem(mylog, FriendlyID, ord(LutFriendlyMode));
  251.         SaveInvertValues := InvertPixelValues;
  252.         if InvertPixelValues then
  253.             SetDlogItem(mylog, InvertValuesID, 1);
  254.         tCreator:='1234';
  255.         tCreator[1]:=TextCreator[1];
  256.         tCreator[2]:=TextCreator[2];
  257.         tCreator[3]:=TextCreator[3];
  258.         tCreator[4]:=TextCreator[4];
  259.         SetDString(mylog, CreatorID, tCreator);
  260.         repeat
  261.             ModalDialog(nil, item);
  262.             if item = BufferSizeID then begin
  263.                     BufferSize := GetDNum(MyLog, BufferSizeID) * 1024;
  264.                     if BufferSize < 1 then begin
  265.                             beep;
  266.                             BufferSize := 1;
  267.                             SetDNum(MyLog, BufferSizeID, BufferSize);
  268.                         end;
  269.                 end;
  270.             if item = ScaleConvolutionsID then begin
  271.                     ScaleConvolutions := not ScaleConvolutions;
  272.                     SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  273.                 end;
  274.             if item = InvertValuesID then begin
  275.                     InvertPixelValues := not InvertPixelValues;
  276.                     SetDlogItem(mylog, InvertValuesID, ord(InvertPixelValues));
  277.                 end;
  278.             if item = InvertYID then begin
  279.                     InvertYCoordinates := not InvertYCoordinates;
  280.                     SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates));
  281.                 end;
  282.             if item = SwitchingID then begin
  283.                     SwitchLUTOnSuspend := not SwitchLUTOnSuspend;
  284.                     SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  285.                 end;
  286.             if item = HighlightID then begin
  287.                     HighlightMode := not HighlightMode;
  288.                     SetDlogItem(mylog, HighlightID, ord(HighlightMode));
  289.                     LoadLUT(info^.ctable);
  290.                 end;
  291.             if item = CreatorID then begin
  292.                 tCreator := GetDString(mylog, item);
  293.                 if length(tCreator)=4 then begin 
  294.                     TextCreator[1]:=tCreator[1];
  295.                     TextCreator[2]:=tCreator[2];
  296.                     TextCreator[3]:=tCreator[3];
  297.                     TextCreator[4]:=tCreator[4];
  298.                 end;
  299.             end;
  300.             if item = OscillatingID then begin
  301.                     OscillatingMovies := not OscillatingMovies;
  302.                     SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies));
  303.                 end;
  304.             if item = FriendlyID then begin
  305.                     NewFriendlyMode := not NewFriendlyMode;
  306.                     SetDlogItem(mylog, FriendlyID, ord(NewFriendlyMode));
  307.                 end;
  308.         until (item = ok) or (item = cancel);
  309.         DisposeDialog(mylog);
  310.         if item = cancel then begin
  311.                 BufferSize := SaveBufferSize;
  312.                 ScaleConvolutions := SaveScaleC;
  313.                 InvertYCoordinates := SaveInvertY;
  314.                 OscillatingMovies := SaveMovies;
  315.                 if PasteControl <> nil then
  316.                     DrawPasteControl;
  317.                 TextCreator := SaveCreator;
  318.             end
  319.         else
  320.             with info^ do begin
  321.                     if InvertPixelValues then begin
  322.                         SaveInfo:=info;
  323.                         for i := 1 to nPics do begin
  324.                                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  325.                                 if info^.fit=uncalibrated then
  326.                                     InvertGrayLevels
  327.                             end; {for}
  328.                         info:=SaveInfo;
  329.                     end else if (InvertPixelValues = false) and SaveInvertValues then begin
  330.                         SaveInfo:=info;
  331.                         for i := 1 to nPics do begin
  332.                                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  333.                                 if isInvertingFunction then
  334.                                     RemoveDensityCalibration;
  335.                             end; {for}
  336.                         info:=SaveInfo;
  337.                     end;
  338.                 end;
  339.         if BufferSize <> SaveBufferSIze then begin
  340.                 PutError('You must quit and restart NIH Image before the Undo and Clipboard buffer size change will take effect.');
  341.                 SaveSettings;
  342.             end;
  343.         if (NewFriendlyMode <> LutFriendlyMode) then begin
  344.             if (not LutFriendlyMode) and (ScreenDepth = 8) then begin
  345.                 SaveInfo := Info;
  346.                 Info := noInfo;
  347.                 okay := LoadCLUTResource(AppleDefaultCLUT);
  348.                 Info := SaveInfo;
  349.             end;
  350.             LutFriendlyMode := NewFriendlyMode;
  351.             if ScreenDepth <= 8 then
  352.                 RestoreScreen;
  353.             UpdateLUT;
  354.         end;
  355.     end;
  356.  
  357.  
  358.     procedure UpdateWindowsMenu;
  359.         var
  360.             i, n: integer;
  361.     begin
  362.         for i := NextImageItem to TileImagesItem do
  363.             SetMenuItem(WindowsMenuH, i, nPics > 1);
  364.         for i := SelectToolsItem to SelectResultsItem do
  365.             CheckItem(WindowsMenuH, i, false);
  366.         SetMenuItem(WindowsMenuH, SelectHistogramItem, HistoWindow <> nil);
  367.         SetMenuItem(WindowsMenuH, SelectPlotItem, PlotWindow <> nil);
  368.         SetMenuItem(WindowsMenuH, SelectResultsItem, ResultsWindow <> nil);
  369.         for i := 1 to nTextWindows do
  370.             CheckItem(WindowsMenuH, WindowsMenuItems - 1 + i, false);
  371.         for i := 1 to nPics do
  372.             CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + i, false);
  373.         if PasteControl = nil then
  374.             SetMenuItemText(WindowsMenuH, PasteControlItem, 'Show Paste Control')
  375.         else
  376.             SetMenuItemText(WindowsMenuH, PasteControlItem, 'Hide Paste Control');
  377.         if CurrentKind < 0 then
  378.             exit(UpdateWindowsMenu); {System Window}
  379.         case CurrentKind of
  380.             ToolKind: 
  381.                 CheckItem(WindowsMenuH, SelectToolsItem, true);
  382.             MapKind: 
  383.                 CheckItem(WindowsMenuH, SelectGrayMapItem, true);
  384.             LUTKind: 
  385.                 CheckItem(WindowsMenuH, SelectLutItem, true);
  386.             InfoKind: 
  387.                 CheckItem(WindowsMenuH, SelectInfoItem, true);
  388.             HistoKind: 
  389.                 CheckItem(WindowsMenuH, SelectHistogramItem, true);
  390.             ProfilePlotKind, CalibrationPLotKind: 
  391.                 CheckItem(WindowsMenuH, SelectPlotItem, true);
  392.             ResultsKind: 
  393.                 CheckItem(WindowsMenuH, SelectResultsItem, true);
  394.             TextKind:  begin
  395.                     if TextInfo <> nil then
  396.                         CheckItem(WindowsMenuH, WindowsMenuItems - 1 + TextInfo^.WindowNum, true);
  397.                 end;
  398.             PicKind: 
  399.                 CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + info^.PicNum, true);
  400.             otherwise
  401.         end;
  402.     end;
  403.  
  404.  
  405.  
  406.  
  407.     procedure CloseAll;
  408.     FORWARD;
  409.  
  410.  
  411.     procedure DoNew;
  412.         const
  413.             ImageID = 4;
  414.             TextID = 5;
  415.             WidthID = 6;
  416.             HeightID = 7;
  417.             TitleID = 8;
  418.         var
  419.             mylog: DialogPtr;
  420.             item, i: integer;
  421.             SaveWidth, SaveHeight: integer;
  422.             SaveTitle: string[31];
  423.             okay, OpenImage: boolean;
  424.  
  425.         procedure SetButtons;
  426.         begin
  427.             SetDlogItem(mylog, ImageID, ord(OpenImage));
  428.             SetDlogItem(mylog, TextID, ord(not OpenImage));
  429.         end;
  430.  
  431.     begin
  432.         InitCursor;
  433.         OpenImage := true;
  434.         SaveWidth := NewPicWidth;
  435.         SaveHeight := NewPicHeight;
  436.         SaveTitle := NewTitle;
  437.         mylog := GetNewDialog(180, nil, pointer(-1));
  438.         SetButtons;
  439.         SetDNum(MyLog, WidthID, NewPicWidth);
  440.         SelectdialogItemText(MyLog, WidthID, 0, 32767);
  441.         SetDNum(MyLog, HeightID, NewPicHeight);
  442.         SetDString(MyLog, TitleID, NewTitle);
  443.         repeat
  444.             ModalDialog(nil, item);
  445.             if item = ImageID then begin
  446.                     OpenImage := true;
  447.                     SetButtons;
  448.                 end;
  449.             if item = TextID then begin
  450.                     OpenImage := false;
  451.                     SetButtons;
  452.                 end;
  453.             if item = WidthID then begin
  454.                     NewPicWidth := GetDNum(MyLog, WidthID);
  455.                     if (NewPicWidth < 0) or (NewPicWidth > MaxPicSize) then begin
  456.                             NewPicWidth := SaveWidth;
  457.                             SetDNum(MyLog, WidthID, NewPicWidth);
  458.                         end;
  459.                 end;
  460.             if item = HeightID then begin
  461.                     NewPicHeight := GetDNum(MyLog, HeightID);
  462.                     if (NewPicHeight < 0) or (NewPicHeight > MaxPicSize) then begin
  463.                             NewPicHeight := SaveHeight;
  464.                             SetDNum(MyLog, HeightID, NewPicHeight);
  465.                         end;
  466.                 end;
  467.         until (item = ok) or (item = cancel);
  468.         if item = ok then
  469.             NewTitle := GetDString(MyLog, TitleID);
  470.         DisposeDialog(mylog);
  471.         if NewPicWidth < 32 then
  472.             NewPicWidth := 32;
  473.         if NewPicHeight < 16 then
  474.             NewPicHeight := 16;
  475.         if item = cancel then begin
  476.                 NewPicWidth := SaveWidth;
  477.                 NewPicHeight := SaveHeight;
  478.                 NewTitle := SaveTitle;
  479.                 exit(DoNew);
  480.             end;
  481.         if OpenImage then begin
  482.                 okay := NewPicWindow(NewTitle, NewPicWidth, NewPicHeight);
  483.                 if okay then
  484.                     if info^.PixMapSize > UndoBufSize then
  485.                         PutWarning;
  486.             end
  487.         else
  488.             okay := MakeNewTextWindow(NewTitle, 500, 400);
  489.     end;
  490.  
  491.  
  492.     procedure DoMenuEvent (MenuChoice: LongInt);
  493.         var
  494.             MenuID, MenuItem, i, ignore: integer;
  495.             name, str: str255;
  496.             dna, RefNum: integer;
  497.             ItemName: str255;
  498.             FontName: str255;
  499.             ok, isSelection: boolean;
  500.             NewStyle: StyleItem;
  501.             t: FateTable;  {Only needed for MakeSkeleton}
  502.             SaveBFInfo: InfoPtr;
  503.             err: OSErr;
  504.     begin
  505.         MenuID := HiWrd(MenuChoice);
  506.         MenuItem := LoWrd(MenuChoice);
  507.         case MenuID of
  508.  
  509.             AppleMenu:  begin
  510.                     if MenuItem = 1 then
  511.                         DoAbout
  512.                     else begin
  513.                             GetMenuItemText(GetMenuHandle(AppleMenu), MenuItem, name);
  514.                             ignore := OpenDeskAcc(name)
  515.                         end;
  516.                 end;
  517.  
  518.             FileMenu:  begin
  519.                     StopDigitizing;
  520.                     isInsertionPoint := false;
  521.                     case MenuItem of
  522.                         NewItem:
  523.                             DoNew;
  524.                         OpenItem:
  525.                             ok := DoOpen('', 0);
  526.                         ImportItem:
  527.                             ok := ImportFile('', 0);
  528.             {-}
  529.                         CloseItem: 
  530.                             if OptionKeyWasDown and (CurrentWindow <> TextKInd) then
  531.                                 CloseAll
  532.                             else
  533.                                 DoClose;
  534.                         SaveItem: 
  535.                             if OptionKeyWasDown and (info^.StackInfo = nil) and (CurrentWindow <> TextKind) then
  536.                                 SaveAll
  537.                             else
  538.                                 SaveFile;
  539.                         SaveAsItem: 
  540.                             case CurrentWindow of
  541.                                 TextKind: 
  542.                                     SaveTextAs;
  543.                                 ResultsKind: 
  544.                                     Export('', 0);
  545.                                 otherwise
  546.                                     SaveAs('', 0);
  547.                             end;
  548.                         ExportItem: 
  549.                             Export('', 0);
  550.            {-}
  551.                         RecordPreferencesItem: 
  552.                             SaveSettings;
  553.                         RevertItem: 
  554.                             with info^ do
  555.                                 if DataType = EightBits then
  556.                                     RevertToSaved
  557.                                 else
  558.                                     RescaleToEightBits;
  559.                         DuplicateItem: 
  560.                             ok := Duplicate('', false);
  561.                         GetInfoItem: 
  562.                             GetInfo;
  563.        {-}
  564.                         PageSetupItem: 
  565.                             if OptionKeyDown then
  566.                                 SetHalftone
  567.                             else
  568.                                 DoPageSetup;
  569.                         PrintItem: 
  570.                             Print(true);
  571.        {-}
  572.                         QuitItem: 
  573.                             finished := true;
  574.                     end;
  575.                     if OpeningRGB then begin
  576.                         ConvertRGBToEightBitColor(true);
  577.                         OpeningRGB := false;
  578.                     end;
  579.                 end;
  580.  
  581.             AcquireMenu: 
  582.                 RunAcqPlugIn(MenuItem);
  583.  
  584.             ExportMenu: 
  585.                 RunExportPlugIn(MenuItem);
  586.  
  587.             EditMenu:  begin
  588.                     StopDigitizing;
  589.                     GetMenuItemText(GetMenuHandle(EditMenu), MenuItem, ItemName);
  590.                     if not SystemEdit(MenuItem - 1) then
  591.                         case MenuItem of
  592.                             UndoItem: 
  593.                                 DoUndo;
  594.              {-}
  595.                             CutItem: 
  596.                                 DoCut;
  597.                             CopyItem: 
  598.                                 DoCopy;
  599.                             PasteItem: 
  600.                                 DoPaste;
  601.                             ClearItem: 
  602.                                 DoClear;
  603.             {-}
  604.                             FillItem: 
  605.                                 if CurrentWindow = TextKind then
  606.                                     DoFind
  607.                                 else
  608.                                     SetupOperation(FillItem);
  609.                             InvertItem, DrawBoundaryItem: 
  610.                                 SetupOperation(MenuItem);
  611.                             DrawScaleItem: 
  612.                                 DrawScale;
  613.              {-}
  614.                             SelectAllItem: 
  615.                                 with info^ do
  616.                                     if CurrentWindow = TextKind then
  617.                                         SelectAllText
  618.                                     else if RoiShowing and EqualRect(RoiRect, PicRect) then
  619.                                         KillRoi
  620.                                     else
  621.                                         SelectAll(true);
  622.                             DeselectItem:
  623.                                 KillRoi;
  624.                             ScaleAndRotateItem: 
  625.                                 ScaleAndRotate;
  626.               {-}
  627.                             RotateLeftItem: 
  628.                                 Rotate(RotateLeft);
  629.                             RotateRightItem: 
  630.                                 Rotate(RotateRight);
  631.                             FlipVerticalItem: 
  632.                                 FlipOrRotate(FlipVertical);
  633.                             FlipHorizontalItem: 
  634.                                 FlipOrRotate(FlipHorizontal);
  635.               {-}
  636.                             UnzoomItem: 
  637.                                 Unzoom;
  638.                             ShowClipboardItem: 
  639.                                 ShowClipboard;
  640.                         end;
  641.                 end;
  642.  
  643.             OptionsMenu:  begin
  644.                     case MenuItem of
  645.                         GrayscaleItem: 
  646.                             ResetGrayMap;
  647.                         LutOptionsItem: 
  648.                             DoLutOptions;
  649.            {-}
  650.                         PreferencesItem: 
  651.                             DoPreferences;
  652.                         PlotOptionsItem: 
  653.                             DoProfilePlotOptions;
  654.                         ScaleToFitItem: 
  655.                             ScaleToFit;
  656.                         ThresholdItem:  begin
  657.                                 if DensitySlicing then
  658.                                     DisableDensitySlice;
  659.                                 if Info^.Thresholding then
  660.                                     DisableThresholding
  661.                                 else begin
  662.                                         SetupLutUndo;
  663.                                         AutoThreshold;
  664.                                     end;
  665.                             end;
  666.                         SliceItem: 
  667.                             if DensitySlicing then
  668.                                 DisableDensitySlice
  669.                             else begin
  670.                                     if info^.thresholding then
  671.                                         DisableThresholding;
  672.                                     EnableDensitySlice;
  673.                                 end;
  674.                     end;
  675.                 end;
  676.  
  677.             ColorTablesMenu: 
  678.                 SwitchColorTables(MenuItem, true);
  679.  
  680.             FontMenu:  begin
  681.                     GetMenuItemText(FontMenuH, MenuItem, FontName);
  682.                     GetFNum(FontName, CurrentFontID);
  683.                     DisplayText(true);
  684.                     if CurrentWindow = TextKind then
  685.                         ChangeFontOrSize;
  686.                 end;
  687.  
  688.             SizeMenu:  begin
  689.                     case MenuItem of
  690.                         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12: 
  691.                             CurrentSize := GetFontSize(MenuItem);
  692.                     end;
  693.                     DisplayText(true);
  694.                     if IsInsertionPoint then
  695.                         UpdatePicWindow;
  696.                     if CurrentWindow = TextKind then
  697.                         ChangeFontOrSize;
  698.                 end;
  699.  
  700.             StyleMenu:  begin
  701.                     case MenuItem of
  702.                         1: 
  703.                             CurrentStyle := [];
  704.                         2, 3, 4, 5, 6:  begin
  705.                                 case MenuItem of
  706.                                     TxBold: 
  707.                                         NewStyle := Bold;
  708.                                     TxItalic: 
  709.                                         NewStyle := Italic;
  710.                                     TxUnderLine: 
  711.                                         NewStyle := Underline;
  712.                                     TxOutLine: 
  713.                                         NewStyle := Outline;
  714.                                     TxShadow: 
  715.                                         NewStyle := Shadow;
  716.                                 end;
  717.                                 if NewStyle in CurrentStyle then
  718.                                     CurrentStyle := CurrentStyle - [NewStyle]
  719.                                 else
  720.                                     CurrentStyle := CurrentStyle + [NewStyle];
  721.                             end;
  722.                         LeftItem: 
  723.                             TextJust := teJustLeft;
  724.                         CenterItem: 
  725.                             TextJust := teJustCenter;
  726.                         RightItem: 
  727.                             TextJust := teJustRight;
  728.                         NoBackgroundItem: 
  729.                             TextBack := NoBack;
  730.                         WithBackgroundItem: 
  731.                             TextBack := WithBack;
  732.                     end; {case}
  733.                     DisplayText(true);
  734.                 end;
  735.  
  736.             PropagateMenu: 
  737.                 DoPropagate(MenuItem);
  738.  
  739.             ProcessMenu:  begin
  740.                     StopDigitizing;
  741.                     SetupUndo;
  742.                     case MenuItem of
  743.                         SmoothItem: 
  744.                             if OptionKeyDown then
  745.                                 Filter(UnweightedAvg, 0, t)
  746.                             else
  747.                                 Filter(WeightedAvg, 0, t);
  748.                         SharpenItem: 
  749.                             Filter(fsharpen, 0, t);
  750.                         ShadowItem:
  751.                           DoShadowFilter; 
  752.                         FindEdgesItem: 
  753.                             Filter(FindEdges, 0, t);
  754.                         RankItem: 
  755.                             DoRankFilter;
  756.                         DitherItem: 
  757.                             Filter(Dither, 0, t);
  758.                         ConvolveItem: 
  759.                             if CurrentWindow = TextKind then
  760.                                 ConvolveUsingText
  761.                             else
  762.                                 Convolve('', 0);
  763.            {-}
  764.                         ImageMathItem: 
  765.                             DoImageMath;
  766.                         ApplyItem: 
  767.                             if CheckCalibration then
  768.                                 ApplyLookupTable;
  769.                         EnhanceItem: 
  770.                             EnhanceContrast;
  771.                         EqualizeItem: 
  772.                             EqualizeHistogram;
  773.                         FixColorsItem:
  774.                             if not isBinaryImage then
  775.                                 FixColors;
  776.                         end;
  777.                 end;
  778.  
  779.             FilterMenu: 
  780.                 RunFilterPlugin(menuItem);
  781.  
  782.             BinaryMenu: 
  783.                 case MenuItem of
  784.                     MakeBinaryItem: 
  785.                         MakeBinary;
  786.                     ErosionItem: 
  787.                         DoErosion;
  788.                     DilationItem: 
  789.                         DoDilation;
  790.                     OpeningItem: 
  791.                         DoOpening;
  792.                     ClosingItem: 
  793.                         DoClosing;
  794.                     SetCountItem: 
  795.                         SetBinaryCount;
  796.                     IterationsItem: 
  797.                         SetIterations;
  798.                     OutlineItem: 
  799.                         filter(OutlineFilter, 0, t);
  800.                     SkeletonizeItem: 
  801.                         MakeSkeleton;
  802.                 end;
  803.  
  804.             ArithmeticMenu: 
  805.                 DoArithmetic(MenuItem, 0);
  806.                 
  807.             fftMenu:
  808.                 case MenuItem of
  809.                     ForewardFFTItem: doFFT(ForewardFFT);
  810.                     InverseFFTItem: doFFT(InverseFFTWithMask);
  811.                     RedisplayItem: RedisplayPowerSpectrum;
  812.                     SwapItem: doSwapQuadrants;
  813.                 end;
  814.  
  815.             BackgroundMenu: 
  816.                 DoBackgroundMenuEvent(MenuItem);
  817.  
  818.             AnalyzeMenu:  begin
  819.                     if MenuItem <> HistogramItem then
  820.                         StopDigitizing;
  821.                     SetupUndo;
  822.                     case MenuItem of
  823.                         MeasureItem: 
  824.                             Measure;
  825.                         AnalyzeItem: 
  826.                             AnalyzeParticles;
  827.                         ShowItem: 
  828.                             ShowResults;
  829.                         OptionsItem: 
  830.                             DoMeasurementOptions;
  831.                         HistogramItem: 
  832.                             DoHistogram;
  833.                         PlotItem: 
  834.                             PlotDensityProfile;
  835.                         PlotSurfaceItem: 
  836.                             PlotSurface;
  837.           {-}
  838.                         SetScaleItem: 
  839.                             SetScale;
  840.                         CalibrateItem: 
  841.                             Calibrate;
  842.                         RedoItem: 
  843.                             RedoMeasurement;
  844.                         DeleteItem: 
  845.                             DeleteMeasurement;
  846.                         ResetItem: 
  847.                             ResetCounter;
  848.                         RestoreItem: 
  849.                             RestoreRoi;
  850.                         MarkItem: 
  851.                             MarkSelection(mCount);
  852.                     end;
  853.                 end;
  854.  
  855.             SpecialMenu:  begin
  856.                     case MenuItem of
  857.                         StartItem: 
  858.                             StartDigitizing;
  859.                         AverageItem: 
  860.                             AverageFrames;
  861.                         SaveBlankFieldItem:  begin
  862.                                 SaveBFInfo := BlankFieldInfo;
  863.                                 BlankFieldInfo := nil; {Prevents shading correction.}
  864.                                 StopDigitizing;
  865.                                 BlankFieldInfo := SaveBFInfo;
  866.                                 SaveBlankField;
  867.                             end;
  868.                         VideoControlItem:
  869.                             ShowVideoDialog;
  870.                         PhotoModeItem: 
  871.                             PhotoMode;
  872.                         LoadMacrosItem:  begin
  873.                                 LoadMacros;
  874.                                 {$ifc not PowerPC}
  875.                                     UnloadSeg(@LoadMacros);
  876.                                 {$endc}
  877.                             end;
  878.                         otherwise
  879.                         if MenuItem >= FirstMacroItem then
  880.                                 RunMacro(MenuItem - FirstMacroItem + 1);
  881.                         {if MenuItem >= FirstMacroItem then begin
  882.                                 if ProfilerInit(collectDetailed, bestTimeBase, 50, 25) = noErr then begin
  883.                                     RunMacro(MenuItem - FirstMacroItem + 1);
  884.                                     err := ProfilerDump('Image.prof');
  885.                                     ProfilerTerm;
  886.                                 end;
  887.                             end;}
  888.                     end;
  889.                 end;
  890.  
  891.             StacksMenu:  begin
  892.                     StopDigitizing;
  893.                     case MenuItem of
  894.                         StackFromWindowsItem: 
  895.                             MakeStack;
  896.                         WindowsFromStackItem: 
  897.                             MakeWindowsFromStack;
  898.                         AddSliceItem: 
  899.                             ok := AddSlice(true);
  900.                         DeleteSliceItem: 
  901.                             DeleteSlice;
  902.                         NextSliceItem, PreviousSliceItem: 
  903.                             ShowNextSlice(MenuItem);
  904.                         MakeMovieItem: 
  905.                             MakeMovie(true);
  906.                         CaptureFramesItem: 
  907.                             CaptureFrames;
  908.                         AnimateItem: 
  909.                             Animate;
  910.                         AverageSlicesItem: 
  911.                             AverageSlices;
  912.                         MakeMontageItem: 
  913.                             MakeMontage;
  914.                         CaptureColorItem: 
  915.                             CaptureColor;
  916.                         RGBToColorItem: 
  917.                             ConvertRGBToEightBitColor(false);
  918.                         ColorToRGBItem: 
  919.                             ConvertEightBitColorToRGB;
  920.                         RGBToHSVItem: 
  921.                             ConvertRGBToHSV;
  922.                         RegisterItem: 
  923.                             DoRegister;
  924.                         ProjectItem: 
  925.                             Project;
  926.                         ResliceItem: 
  927.                             Reslice;
  928.                         StackInfoItem: 
  929.                             DoStackInfo;
  930.                         otherwise
  931.                             beep
  932.                     end;
  933.                 end;
  934.  
  935.             WindowsMenu:  begin
  936.                     if MenuItem <> PasteControlItem then
  937.                         StopDigitizing;
  938.                     case MenuItem of
  939.                         NextImageItem: 
  940.                             ShowNextImage;
  941.                         CascadeImagesItem: 
  942.                             CascadeImages;
  943.                         TileImagesItem: 
  944.                             TileImages;
  945.                         PasteControlItem: 
  946.                             if PasteControl = nil then
  947.                                 ShowPasteControl
  948.                             else
  949.                                 ignore := CloseAWindow(PasteControl);
  950.             {-}
  951.                         SelectToolsItem: 
  952.                             SelectWindow(ToolWindow);
  953.                         SelectGrayMapItem: 
  954.                             SelectWindow(MapWindow);
  955.                         SelectLutItem: 
  956.                             SelectWindow(LUTWindow);
  957.                         SelectInfoItem: 
  958.                             SelectWindow(InfoWindow);
  959.                         SelectHistogramItem: 
  960.                             if HistoWindow <> nil then
  961.                                 SelectWindow(HistoWindow);
  962.                         SelectPlotItem: 
  963.                             if PlotWindow <> nil then
  964.                                 SelectWindow(PlotWindow);
  965.                         SelectResultsItem: 
  966.                             if ResultsWindow <> nil then
  967.                                 SelectWindow(ResultsWindow);
  968.           {-}
  969.                         otherwise
  970.                             if MenuItem <= (WindowsMenuItems - 1 + nTextWindows) then
  971.                                 SelectWindow(TextWindow[MenuItem - (WindowsMenuItems - 1)])
  972.                             else
  973.                                 SelectWindow(PicWindow[MenuItem - (WindowsMenuItems + nTextWindows)]);
  974.                     end;
  975.                 end;
  976.  
  977.             UserMenu: 
  978.                 DoUserMenuEvent(MenuItem);
  979.             otherwise
  980.         end;
  981.         HiliteMenu(0);
  982.         RoiUpdateTime := 0;
  983.     end;
  984.  
  985.  
  986.     procedure DoFreehand;
  987.         var
  988.             finish: point;
  989.             event: EventRecord;
  990.             wright, wbottom: integer;
  991.             b: boolean;
  992.     begin
  993.         SetPort(info^.wptr);
  994.         PenPat(AntPattern[PatIndex]);
  995.         PenSize(1, 1);
  996.         with info^.wptr^.PortRect do begin
  997.                 wright := right;
  998.                 wbottom := bottom;
  999.             end;
  1000.         while Button do begin
  1001.                 GetMouse(finish);
  1002.                 with finish do begin
  1003.                         if h < 0 then
  1004.                             h := 0;
  1005.                         if v < 0 then
  1006.                             v := 0;
  1007.                         if h > wright then
  1008.                             h := wright;
  1009.                         if v > wbottom then
  1010.                             v := wbottom;
  1011.                         if (xCoordinates^[nCoordinates] <> h) or (yCoordinates^[nCoordinates] <> v) then begin
  1012.                                 if nCoordinates < MaxCoordinates then
  1013.                                     nCoordinates := nCoordinates + 1
  1014.                                 else
  1015.                                     beep;
  1016.                                 LineTo(h, v);
  1017.                                 xCoordinates^[nCoordinates] := h;
  1018.                                 yCoordinates^[nCoordinates] := v;
  1019.                                 wait(1);
  1020.                             end; {if mouse has moved}
  1021.                     end; {with}
  1022.             end; {while Button}
  1023.     end;
  1024.  
  1025.  
  1026.     procedure DoPolygon (start: point);
  1027.         var
  1028.             Finish, OldFinish: point;
  1029.             finished, DoubleClick, done: boolean;
  1030.             ticks, MouseUpTime, LastMouseUpTime: LongInt;
  1031.             wright, wbottom: integer;
  1032.             StartRect: rect;
  1033.             MouseDown, MouseUpEvent: boolean;
  1034.     begin
  1035.         DrawLabels('DX:', 'DY:', 'Length:');
  1036.         SetPort(info^.wptr);
  1037.         PenMode(PatXor);
  1038.         PenSize(1, 1);
  1039.         if CurrentTool = PolygonTool then begin
  1040.                 Pt2Rect(Start, Start, StartRect);
  1041.                 InsetRect(StartRect, -4, -4);
  1042.                 FrameRect(StartRect);
  1043.             end
  1044.         else
  1045.             SetRect(StartRect, 0, 0, 0, 0);
  1046.         finish := start;
  1047.         finished := false;
  1048.         with info^.wptr^.PortRect do begin
  1049.                 wright := right;
  1050.                 wbottom := bottom;
  1051.             end;
  1052.         MouseUpTime := 0;
  1053.         done := false;
  1054.         MouseUpEvent := false;
  1055.         MouseDown := button;
  1056.         repeat
  1057.             ShowDxDy(0, 0);
  1058.             repeat
  1059.                 OldFinish := finish;
  1060.                 GetMouse(finish);
  1061.                 with finish do begin
  1062.                         if h < 0 then begin
  1063.                                 h := 0;
  1064.                                 done := CurrentTool = LineTool;
  1065.                             end;
  1066.                         if v < 0 then begin
  1067.                                 v := 0;
  1068.                                 done := CurrentTool = LineTool;
  1069.                             end;
  1070.                         if h > wright then begin
  1071.                                 h := wright;
  1072.                                 done := CurrentTool = LineTool;
  1073.                             end;
  1074.                         if v > wbottom then begin
  1075.                                 v := wbottom;
  1076.                                 done := CurrentTool = LineTool;
  1077.                             end;
  1078.                     end;
  1079.                 if not EqualPt(finish, OldFinish) then begin
  1080.                         ticks := TickCount;
  1081.                         repeat
  1082.                         until TickCount <> ticks;
  1083.                         MoveTo(start.h, start.v);
  1084.                         LineTo(OldFinish.h, OldFinish.v);
  1085.                         MoveTo(start.h, start.v);
  1086.                         LineTo(finish.h, finish.v);
  1087.                         ShowDxDy(abs(finish.h - start.h), abs(finish.v - start.v));
  1088.                     end;
  1089.                 if button <> MouseDown then begin
  1090.                         MouseUpEvent := not button;
  1091.                         MouseDown := button;
  1092.                     end;
  1093.             until MouseUpEvent;
  1094.             MouseUpEvent := false;
  1095.             LastMouseUpTime := MouseUpTime;
  1096.             MouseUpTime := TickCount;
  1097.             DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish);
  1098.             if nCoordinates < MaxCoordinates then
  1099.                 nCoordinates := nCoordinates + 1
  1100.             else
  1101.                 beep;
  1102.             xCoordinates^[nCoordinates] := finish.h;
  1103.             yCoordinates^[nCoordinates] := finish.v;
  1104.             start := finish;
  1105.             Finished := (PtInRect(finish, StartRect) or DoubleClick or done) and (nCoordinates > 2);
  1106.         until finished;
  1107.         FlushEvents(EveryEvent, 0);
  1108.     end;
  1109.  
  1110.  
  1111.     procedure MakePolygon (event: EventRecord);
  1112.         var
  1113.             Start: point;
  1114.             i: integer;
  1115.     begin
  1116.         with info^ do begin
  1117.                 start := event.where;
  1118.                 SetPort(wptr);
  1119.                 PenNormal;
  1120.                 xCoordinates^[1] := Start.h;
  1121.                 yCoordinates^[1] := Start.v;
  1122.                 nCoordinates := 1;
  1123.                 MoveTo(start.h, start.v);
  1124.                 case CurrentTool of
  1125.                     FreehandTool:  begin
  1126.                             DoFreehand;
  1127.                             with Start do
  1128.                                 LineTo(h, v);
  1129.                         end;
  1130.                     PolygonTool: 
  1131.                         DoPolygon(start);
  1132.                 end;
  1133.                 if nCoordinates > 2 then begin
  1134.                         ConvertCoordinates;
  1135.                         if CurrentTool = PolygonTool then
  1136.                             MakeOutline(PolygonRoi)
  1137.                         else
  1138.                             MakeOutline(FreehandRoi);
  1139.                     end
  1140.                 else begin
  1141.                         KillRoi;
  1142.                         UpdatePicWindow;
  1143.                     end;
  1144.             end; {with}
  1145.     end;
  1146.  
  1147.  
  1148.     procedure MakeLineRoi (event: EventRecord);
  1149.         var
  1150.             Start: point;
  1151.     begin
  1152.         if NoUndo then
  1153.             exit(MakeLineRoi);
  1154.         start := event.where;
  1155.         with Info^ do begin
  1156.                 WhatToUndo := NothingToUndo;
  1157.                 measuring := false;
  1158.                 if LOIType = Straight then begin
  1159.                         DoObject(LineObj, event);
  1160.                         RoiType := LineRoi;
  1161.                         MakeRegion;
  1162.                         RoiShowing := true;
  1163.                         SetupUndo;
  1164.                         exit(MakeLineRoi);
  1165.                     end;
  1166.                 SetPort(wptr);
  1167.                 PenNormal;
  1168.                 MoveTo(start.h, start.v);
  1169.                 xCoordinates^[1] := Start.h;
  1170.                 yCoordinates^[1] := Start.v;
  1171.                 nCoordinates := 1;
  1172.             end; {with info}
  1173.         if LOIType = Freehand then
  1174.             DoFreehand
  1175.         else
  1176.             DoPolygon(start);
  1177.         if nCoordinates > 1 then
  1178.             case LoiType of
  1179.                 freehand: 
  1180.                     MakeNonStraightLineRoi(FreeLineRoi);
  1181.                 segmented: 
  1182.                     MakeNonStraightLineRoi(SegLineRoi);
  1183.             end
  1184.         else
  1185.             with info^ do begin
  1186.                     RoiShowing := false;
  1187.                     RoiType := NoRoi;
  1188.                     UpdatePicWindow;
  1189.                 end;
  1190.     end;
  1191.  
  1192.  
  1193.     procedure DoProfilePlot (event: EventRecord);
  1194.         var
  1195.             ulength, clength: extended;
  1196.     begin
  1197.         with Info^ do begin
  1198.                 WhatToUndo := NothingToUndo;
  1199.                 measuring := false;
  1200.                 DoObject(LineObj, event);
  1201.                 RoiType := LineRoi;
  1202.                 MakeRegion;
  1203.                 RoiShowing := true;
  1204.                 SetupUndo;
  1205.                 GetLengthOrPerimeter(ulength, clength);
  1206.                 if ulength > 0 then
  1207.                     PlotDensityProfile
  1208.             end;
  1209.     end;
  1210.  
  1211.  
  1212.     procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr);
  1213.   {Handles mouse down events in the content region of image windows.}
  1214.         var
  1215.             r: rect;
  1216.             str: str255;
  1217.             hloc, vloc: integer;
  1218.             tool: ToolType;
  1219.             start: Point;
  1220.     begin
  1221.         SetPort(info^.wptr);
  1222.         if Digitizing then
  1223.             if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1224.                 StopDigitizing;
  1225.         GlobalToLocal(event.where);
  1226.         IsInsertionPoint := false;
  1227.         with info^ do
  1228.             if RoiShowing then
  1229.                 if EqualRect(RoiRect, PicRect) and (SelectionMode = NewSelection) then {if Select All}
  1230.                     if not (OpPending and (CurrentOp = PasteOp)) then begin
  1231.                             KillRoi;
  1232.                             MouseState := NotInRoi;
  1233.                             exit(DoMouseDownInWindow);
  1234.                         end;
  1235.         if MouseState <> NotInRoi then
  1236.             exit(DoMouseDownInWindow);
  1237.         if SpaceBarDown and (CurrentTool <> TextTool) then
  1238.             tool := grabber
  1239.         else
  1240.             tool := CurrentTool;
  1241.         if (SelectionMode = NewSelection) and not ((tool = MagnifyingGlass) or (tool = Grabber)) then
  1242.             KillRoi;
  1243.         SetupUndo;
  1244.         case tool of
  1245.             SelectionTool: 
  1246.                 DoObject(SelectionRect, event);
  1247.             PolygonTool, FreehandTool: 
  1248.                 MakePolygon(event);
  1249.             OvalSelectionTool: 
  1250.                 DoObject(SelectionOval, event);
  1251.             LineTool: 
  1252.                 MakeLineRoi(event);
  1253.             MagnifyingGlass: 
  1254.                 ZoomIn(event);
  1255.             Grabber: 
  1256.                 Scroll(event);
  1257.             Pencil, Brush, Eraser: 
  1258.                 DoBrush(event);
  1259.             SprayCanTool: 
  1260.                 DoSprayCan;
  1261.             Ruler: 
  1262.                 if OptionKeyDown or ControlKeyDown then
  1263.                     PutError('Use the line selection tool and Measure to measure path lengths.')
  1264.                 else begin
  1265.                         DoObject(LineObj, event);
  1266.                         WhatToUndo := UndoEdit;
  1267.                     end;
  1268.             PaintBucket: 
  1269.                 DoFill(event);
  1270.             TextTool: 
  1271.                 DoText(event.where);
  1272.             PlotTool: 
  1273.                 DoProfilePlot(event);
  1274.             PickerTool: 
  1275.                 if BitAnd(Event.modifiers, OptionKey) = OptionKey then
  1276.                     GetBackgroundColor(event)
  1277.                 else
  1278.                     GetForegroundColor(event);
  1279.             CrossHairTool: 
  1280.                 DoPoints(event);
  1281.             AngleTool: 
  1282.                 FindAngle(event);
  1283.             Wand:  begin
  1284.                     if Digitizing then
  1285.                         StopDigitizing;
  1286.                     start := event.where;
  1287.                     ScreenToOffscreen(start);
  1288.                     AutoOutline(start);
  1289.                 end;
  1290.             otherwise
  1291.                 beep;
  1292.         end;
  1293.     end;
  1294.  
  1295.  
  1296.     procedure DoPopupMenusInTools;
  1297.         var
  1298.             Item: integer;
  1299.             ticks: LongInt;
  1300.  
  1301.         procedure DrawCurrentTool;
  1302.         begin
  1303.             InvalRect(ToolRect[CurrentTool]);
  1304.             BeginUpdate(ToolWindow);
  1305.             DrawTools;
  1306.             EndUpdate(ToolWindow);
  1307.         end;
  1308.  
  1309.     begin
  1310.         DrawCurrentTool;
  1311.         ticks := TickCount;
  1312.         repeat
  1313.         until (not button) or (TickCount > ticks + 20);
  1314.         if button and (TickCount > (ticks + 20)) then
  1315.             with ToolRect[CurrentTool] do begin
  1316.                     Item := PopUpMenu(LineToolMenuH, left, top, ord(LOIType) + 1);
  1317.                     case Item of
  1318.                         1: 
  1319.                             LOIType := Straight;
  1320.                         2: 
  1321.                             LOIType := Freehand;
  1322.                         3: 
  1323.                             LOIType := Segmented;
  1324.                         otherwise
  1325.                     end;
  1326.                     DrawCurrentTool;
  1327.                 end;
  1328.     end;
  1329.  
  1330.  
  1331.     procedure DoMouseDownInTools (loc: point);
  1332.  {Handles mouse down events in the tool palette.}
  1333.         var
  1334.             r: rect;
  1335.             OddTool, DoubleClick: boolean;
  1336.             ToolNum, i: integer;
  1337.     begin
  1338.         SetPort(ToolWindow);
  1339.         GlobalToLocal(loc);
  1340.         if loc.v <= StartOfLines then begin
  1341.                 PreviousTool := CurrentTool;
  1342.                 OddTool := loc.h < tmiddle;
  1343.                 ToolNum := (loc.v div tmiddle) * 2;
  1344.                 if not OddTool then
  1345.                     ToolNum := ToolNum + 1;
  1346.                 CurrentTool := ToolType(ToolNum);
  1347.                 isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = LineTool);
  1348.                 DoubleClick := (TickCount - ToolTime) < GetDblTime;
  1349.                 ToolTime := TickCount;
  1350.                 InvalRect(ToolRect[CurrentTool]);
  1351.                 InvalRect(ToolRect[PreviousTool]);
  1352.                 IsInsertionPoint := false;
  1353.                 if DoubleClick and (CurrentTool = PreviousTool) then
  1354.                     case CurrentTool of
  1355.                         MagnifyingGlass: 
  1356.                             Unzoom;
  1357.                         SelectionTool:  begin
  1358.                                 StopDigitizing;
  1359.                                 SelectAll(true);
  1360.                             end;
  1361.                         SprayCanTool: 
  1362.                             SetSprayCanSize;
  1363.                         Brush: 
  1364.                             SetBrushSize;
  1365.                         LineTool: 
  1366.                             SetScale;
  1367.                         PolygonTool: 
  1368.                             DoMeasurementOptions;
  1369.                         FreehandTool: 
  1370.                             Calibrate;
  1371.                         ruler: 
  1372.                             SetLineWidth;
  1373.                         PlotTool: 
  1374.                             DoProfilePlotOptions;
  1375.                         Eraser: 
  1376.                             if info <> NoInfo then begin
  1377.                                     KillRoi;
  1378.                                     SetupUndo;
  1379.                                     WhatToUndo := UndoClear;
  1380.                                     StopDigitizing;
  1381.                                     SelectAll(false);
  1382.                                     DoOperation(eraseOp);
  1383.                                 end;
  1384.                         LutTool, Wand: 
  1385.                             if DensitySlicing then
  1386.                                 DisableDensitySlice
  1387.                             else begin
  1388.                                     if Info^.Thresholding then
  1389.                                         ResetGrayMap;
  1390.                                     if OptionKeyDown then
  1391.                                         AutoDensitySlice;
  1392.                                     EnableDensitySlice;
  1393.                                 end;
  1394.                         PickerTool: 
  1395.                             if info^.LutMode <> PseudoColor then begin  {Switch to pseudocolor mode}
  1396.                                     DisableDensitySlice;
  1397.                                     UpdateLUT;
  1398.                                     CurrentTool := LutTool;
  1399.                                     isSelectionTool := false;
  1400.                                     InvalRect(ToolRect[CurrentTool]);
  1401.                                 end
  1402.                             else
  1403.                                 ResetGrayMap;
  1404.                         otherwise
  1405.                     end; {case}
  1406.                 if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) and (CurrentTool <> Wand) then
  1407.                     KillRoi;
  1408.                 if not DoubleClick and (CurrentTool = LineTool) then
  1409.                     KillRoi;
  1410.                 with info^ do
  1411.                     if RoiShowing then
  1412.                         if EqualRect(RoiRect, PicRect) and not isSelectionTool then {if Select All}
  1413.                             KillRoi;
  1414.                 if (CurrentTool = SelectionTool) or (CurrentTool = CrossHairTool) then begin
  1415.                         InfoMessage := '';
  1416.                         if mCount > 0 then
  1417.                             ShowInfo;
  1418.                     end;
  1419.                 RoiMode := MoveMode;
  1420.                 if CurrentTool = LineTool then begin
  1421.                         if Button then
  1422.                             DoPopUpMenusInTools;
  1423.                         if (LoiType = Straight) and (LineWidth <> 1) then begin
  1424.                                 LineWidth := 1;
  1425.                                 UpdateRoiLineWidth;
  1426.                                 ShowLineWidth;
  1427.                             end;
  1428.                     end;
  1429.             end
  1430.         else begin
  1431.                 for i := 1 to nLineTypes do begin
  1432.                         r := lines[i];
  1433.                         with r do begin
  1434.                                 left := left - 13;
  1435.                                 top := top - 2;
  1436.                                 right := right + 2;
  1437.                                 bottom := bottom + 2;
  1438.                             end;
  1439.                         if i = 1 then
  1440.                             with r do
  1441.                                 top := top - 7;
  1442.                         if PtInRect(loc, r) then begin
  1443.                                 with lines[i] do
  1444.                                     LineWidth := bottom - top;
  1445.                                 LineIndex := i;
  1446.                             end;
  1447.                     end;
  1448.                 EraseRect(CheckRect);
  1449.                 InvalRect(CheckRect);
  1450.                 UpdateRoiLineWidth;
  1451.             end;
  1452.     end;
  1453.  
  1454.  
  1455.     procedure ScaleToFitScreen;
  1456.         var
  1457.             trect: rect;
  1458.             ignore: boolean;
  1459.     begin
  1460.         with info^ do begin
  1461.                 MoveWindow(wptr, PicLeftBase, PicTopBase, true);
  1462.                 SetRect(trect, 0, 0, ScreenWidth, ScreenHeight);
  1463.                 ScaleImageWindow(trect);
  1464.                 wrect := trect;
  1465.                 SizeWindow(wptr, trect.right, trect.bottom, true);
  1466.             end;
  1467.     end;
  1468.  
  1469.  
  1470.     procedure DoDrag (WhichWindow: WindowPtr; loc: point);
  1471.         var
  1472.             WinRect, DragBounds, trect: rect;
  1473.             kind: integer;
  1474.     begin
  1475.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1476.         if kind = PicKind then begin
  1477.                 with info^ do begin  {Save window location}
  1478.                         GetWindowRect(wptr, trect);
  1479.                         savehloc := trect.left;
  1480.                         savevloc := trect.top;
  1481.                     end;
  1482.                 PicLeft := PicLeftBase;
  1483.                 PicTop := PicTopBase;
  1484.             end;
  1485.         DragBounds := qd.ScreenBits.bounds;
  1486.         DragWindow(WhichWindow, loc, DragBounds);
  1487.         if (info^.PictureType = FrameGrabberType) or OptionKeyDown then begin
  1488.                 GetWindowRect(WhichWindow, trect);
  1489.                 MoveWindow(WhichWindow, band(trect.left, $fffc), trect.top, true);
  1490.             end;
  1491.         if WhichWindow = InfoWindow then
  1492.             ShowInfo;
  1493.         if WhichWindow = ResultsWindow then begin
  1494.                 GetWindowRect(WhichWindow, trect);
  1495.                 ResultsTop := trect.top;
  1496.                 ResultsLeft := trect.left;
  1497.             end;
  1498.     end;
  1499.  
  1500.  
  1501.     procedure UpdateMenus;
  1502.     begin
  1503.         OptionKeyWasDown := OptionKeyDown;
  1504.         CurrentKind := CurrentWindow;
  1505.         UpdateFileMenu;
  1506.         UpdateEditMenu;
  1507.         UpdateOptionsMenu;
  1508.         UpdateTextItems;
  1509.         UpdateProcessMenu;
  1510.         UpdateAnalysisMenu;
  1511.         UpdateSpecialMenu;
  1512.         UpdateStacksMenu;
  1513.         UpdateWindowsMenu;
  1514.     end;
  1515.  
  1516.  
  1517.     function BalloonHelp: boolean;
  1518.     begin
  1519.         if not System7 then begin
  1520.                 BalloonHelp := false;
  1521.                 exit(BalloonHelp);
  1522.             end;
  1523.         BalloonHelp := HMGetBalloons;
  1524.     end;
  1525.  
  1526.  
  1527.     procedure DoMouseDown (event: EventRecord);
  1528.     {Handle mouse-down events}
  1529.         var
  1530.             WhichWindow: WindowPtr;
  1531.             ThePart, ignore, kind: integer;
  1532.             trect: rect;
  1533.     begin
  1534.         ThePart := FindWindow(event.where, WhichWindow);
  1535.         case ThePart of
  1536.             InDesk: 
  1537.                 ;
  1538.             InMenuBar:  begin
  1539.                     UpdateMenus;
  1540.                     DoMenuEvent(MenuSelect(event.where));
  1541.                 end;
  1542.             InSysWindow: 
  1543.                 SystemClick(Event, WhichWindow);
  1544.             InContent:  begin
  1545.             {The Tools, Map, LUT and PasteControl windows do not have
  1546.             to be activated to process the mouse-down event.}
  1547.                     RoiUpdateTime := 0;
  1548.                     if WhichWindow = ToolWindow then begin
  1549.                             if BalloonHelp then
  1550.                                 SelectWindow(ToolWindow);
  1551.                             DoMouseDownInTools(event.where);
  1552.                             exit(DoMouseDown);
  1553.                         end;
  1554.                     if WhichWindow = MapWindow then begin
  1555.                             if BalloonHelp then
  1556.                                 SelectWindow(MapWindow);
  1557.                             DoMouseDownInMap;
  1558.                             exit(DoMouseDown)
  1559.                         end;
  1560.                     if WhichWindow = LUTWindow then begin
  1561.                             if BalloonHelp then
  1562.                                 SelectWindow(LUTWindow);
  1563.                             DoMouseDownInLUT(event);
  1564.                             exit(DoMouseDown)
  1565.                         end;
  1566.                     if WhichWindow = PasteControl then begin
  1567.                             DoMouseDownInPasteControl(event.where);
  1568.                             exit(DoMouseDown)
  1569.                         end;
  1570.                     if WhichWindow <> FrontWindow then begin
  1571.                         {Image windows, text windows and the Result window
  1572.                          must be activated if they are not the current window.}
  1573.                         SelectWindow(WhichWindow);
  1574.                         exit(DoMouseDown);
  1575.                     end;
  1576.                     if WhichWindow = ResultsWindow then begin
  1577.                             DoMouseDownInResults(event.where);
  1578.                             exit(DoMouseDown)
  1579.                         end;
  1580.                     kind := WindowPeek(WhichWindow)^.WindowKind;
  1581.                     if Kind = TextKind then begin
  1582.                             DoMouseDownInText(Event, WhichWindow);
  1583.                             exit(DoMouseDown)
  1584.                         end;
  1585.                     if kind = PicKind then
  1586.                         DoMouseDownInWindow(Event, WhichWindow);
  1587.                 end;
  1588.             InDrag: 
  1589.                 DoDrag(WhichWindow, event.where);
  1590.             InGrow: 
  1591.                 DoGrow(WhichWindow, event);
  1592.             InGoAway: 
  1593.                 if TrackGoAway(WhichWindow, event.where) then
  1594.                     if OptionKeyDown and (CurrentWindow = PicKind) then
  1595.                         CloseAll
  1596.                     else begin
  1597.                             if WhichWindow <> VideoControl then
  1598.                                 StopDigitizing;
  1599.                             ignore := CloseAWindow(WhichWindow);
  1600.                         end;
  1601.             InZoomIn, InZoomOut: 
  1602.                 with info^ do
  1603.                     case WindowState of
  1604.                         NormalWindow:  begin
  1605.                                 if digitizing then
  1606.                                     exit(DoMouseDown);
  1607.                                 ScaleToFit;
  1608.                                 if ScaleToFitWindow then
  1609.                                     ScaleToFitScreen;
  1610.                             end;
  1611.                         TiledSmall, TiledSmallScaled:  begin
  1612.                                 if WindowState = TiledSmall then begin
  1613.                                         ScaleToFitWindow := true;
  1614.                                         WindowState := TiledBig;
  1615.                                     end
  1616.                                 else
  1617.                                     WindowState := TiledBigScaled;
  1618.                                 savewrect := wrect;
  1619.                                 SaveSrcRect := SrcRect;
  1620.                                 SaveMagnification := magnification;
  1621.                                 GetWindowRect(wptr, trect);
  1622.                                 savehloc := trect.left;
  1623.                                 savevloc := trect.top;
  1624.                                 ScaleToFitScreen;
  1625.                                 UpdatePicWindow;
  1626.                             end;
  1627.                         TiledBig:  begin
  1628.                                 ScaleToFitWindow := false;
  1629.                                 WindowState := TiledSmall;
  1630.                                 wrect := savewrect;
  1631.                                 SrcRect := SaveSrcRect;
  1632.                                 magnification := SaveMagnification;
  1633.                                 HideWindow(wptr);
  1634.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1635.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1636.                                 ShowWindow(wptr);
  1637.                                 UpdatePicWindow;
  1638.                                 magnification := 1.0;
  1639.                                 UpdateTitleBar;
  1640.                             end;
  1641.                         TiledBigScaled:  begin
  1642.                                 WindowState := TiledSmallScaled;
  1643.                                 wrect := savewrect;
  1644.                                 SrcRect := PicRect;
  1645.                                 HideWindow(wptr);
  1646.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1647.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1648.                                 ShowWindow(wptr);
  1649.                                 UpdatePicWindow;
  1650.                                 if PicRect.right <> 0 then
  1651.                                     magnification := wrect.right / PicRect.right;
  1652.                                 UpdateTitleBar;
  1653.                             end;
  1654.                     end; {case WindowState}
  1655.         end; {case thePart}
  1656.     end;
  1657.  
  1658.  
  1659.     procedure NudgeRoi (key: integer);
  1660.         var
  1661.             dh, dv: integer;
  1662.     begin
  1663.         with info^ do begin
  1664.                 if not RoiShowing then
  1665.                     exit(NudgeRoi);
  1666.                 if OpPending and (CurrentOp <> PasteOp) then begin
  1667.                     KillRoi;
  1668.                     RestoreRoi;
  1669.                 end;
  1670.                 case key of
  1671.                     LeftArrow:  begin
  1672.                             dh := -1;
  1673.                             dv := 0
  1674.                         end;
  1675.                     RightArrow:  begin
  1676.                             dh := 1;
  1677.                             dv := 0
  1678.                         end;
  1679.                     UpArrow:  begin
  1680.                             dh := 0;
  1681.                             dv := -1
  1682.                         end;
  1683.                     DownArrow:  begin
  1684.                             dh := 0;
  1685.                             dv := 1
  1686.                         end;
  1687.                 end;
  1688.                 if OptionKeyDown then begin
  1689.                         if RoiType = RectRoi then
  1690.                             with RoiRect do begin
  1691.                                     right := right + dh;
  1692.                                     if right < left + 2 then
  1693.                                         right := left + 2;
  1694.                                     bottom := bottom + dv;
  1695.                                     if bottom < top + 2 then
  1696.                                         bottom := top + 2;
  1697.                                     MakeRegion;
  1698.                                 end
  1699.                         else
  1700.                             beep;
  1701.                     end
  1702.                 else begin
  1703.                         OffsetRgn(roiRgn, dh, dv);
  1704.                         RoiRect := roiRgn^^.rgnBBox;
  1705.                     end;
  1706.                 RoiNudged := true;
  1707.                 RoiUpdateTime := 0;
  1708.             end;
  1709.     end;
  1710.  
  1711.  
  1712.     procedure DoKeyDown (event: EventRecord);
  1713.         var
  1714.             ch: char;
  1715.             ich, KeyCode: integer;
  1716.     begin
  1717.         Ch := chr(band(Event.message, CharCodeMask));
  1718.         ich := ord(ch);
  1719. {ShowMessage(long2str(ich));}
  1720.         KeyCode := bsr(band(Event.message, KeyCodeMask), 8);
  1721.         if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin
  1722.                 UpdateMenus;
  1723.                 if OptionKeyWasDown then begin
  1724.                         case KeyCode of
  1725.                             1: 
  1726.                                 ch := 'S';
  1727.                             3: 
  1728.                                 ch := 'F';
  1729.                             5: 
  1730.                                 ch := 'G';
  1731.                             8: 
  1732.                                 ch := 'C';
  1733.                             9: 
  1734.                                 ch := 'V';
  1735.                             13: 
  1736.                                 ch := 'W';
  1737.                             17: 
  1738.                                 ch := 'T';
  1739.                             24: 
  1740.                                 ch := '=';
  1741.                             35: 
  1742.                                 ch := 'P';
  1743.                             44: 
  1744.                                 ch := '/';
  1745.                         end;
  1746.                     end;
  1747.                 DoMenuEvent(MenuKey(Ch));
  1748.                 exit(DoKeyDown)
  1749.             end;
  1750.         if CurrentWindow = TextKind then begin
  1751.                 DoKeyDownInText(ch);
  1752.                 exit(DoKeyDown)
  1753.             end;
  1754.         with info^ do
  1755.             if (CurrentTool = TextTool) and IsInsertionPoint and (ord(ch) <> FunctionKey) then
  1756.                 DrawCharacter(ch)
  1757.             else if ch = BackSpace then
  1758.                 DoClear
  1759.             else if RoiShowing and (ich >= LeftArrow) and (ich <= DownArrow) then
  1760.                 NudgeRoi(ich)
  1761.             else if (StackInfo <> nil) and (ch in ['<', ',', chr(PageUp), '>', '.', chr(PageDown), chr(HomeKey), chr(EndKey)]) then begin
  1762.                     if ch in ['<', ',', chr(PageUp)] then
  1763.                         ShowNextSlice(PreviousSliceItem)
  1764.                     else if ch in ['>', '.', chr(PageDown)] then
  1765.                         ShowNextSlice(NextSliceItem)
  1766.                     else if (ich = HomeKey) or (ich = EndKey) then
  1767.                         ShowFirstOrLastSlice(ich);
  1768.                 end
  1769.             else if nMacros > 0 then
  1770.                 RunKeyMacro(ch, KeyCode);
  1771.     end;
  1772.  
  1773.  
  1774.     procedure DoActivate (event: EventRecord);
  1775.         var
  1776.             WhichWindow: WindowPtr;
  1777.             Activating, SwitchingWindows, isOK: boolean;
  1778.             I, kind: integer;
  1779.             NewInfo: InfoPtr;
  1780.     begin
  1781.         WhichWindow := WindowPtr(event.message);
  1782.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1783.         Activating := odd(event.modifiers);
  1784.         case kind of
  1785.             PicKind:  begin
  1786.                     if Activating then begin
  1787.                             NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon);
  1788.                             SwitchingWindows := NewInfo <> Info;
  1789.                             if SwitchingWindows then begin
  1790.                                     StopDigitizing;
  1791.                                     SaveRoi;
  1792.                                     DisableDensitySlice;
  1793.                                 end;
  1794.                             Info := NewInfo;
  1795.                             if SwitchingWindows then
  1796.                                 ActivateWindow;
  1797.                             Measuring := false;
  1798.                             with info^ do begin
  1799.                                     LoadLUT(cTable);
  1800.                                     DrawMap;
  1801.                                     if digitizing and HighlightSaturatedPixels then
  1802.                                         HighlightPixels;
  1803.                                     GenerateValues;
  1804.                                     if fit = uncalibrated then
  1805.                                         DrawLabels('', '', '');
  1806.                                 end; {with}
  1807.                         end
  1808.                     else
  1809.                         KillOperation; {Deactivate}
  1810.                 end;
  1811.             ResultsKind: 
  1812.                 UpdateResultsWindow;
  1813.             TextKind: 
  1814.                 ActivateTextWindow(WhichWindow, Activating);
  1815.             otherwise
  1816.         end; {case}
  1817.         if not activating then begin
  1818.                 WhichWindow := FrontWindow;
  1819.                 if WhichWindow <> nil then begin
  1820.                         kind := WindowPeek(WhichWindow)^.WindowKind;
  1821.                         if kind < 0 then
  1822.                             ConverToSystemClipboard; {DA has become active}
  1823.                     end;
  1824.             end;
  1825.     end;
  1826.  
  1827.  
  1828.     procedure DoUpdate (event: EventRecord);
  1829.         var
  1830.             WhichWindow: WindowPtr;
  1831.             SaveInfo: InfoPtr;
  1832.             kind: integer;
  1833.     begin
  1834.         WhichWindow := WindowPtr(event.message);
  1835.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1836.         BeginUpdate(WhichWindow);
  1837.         case kind of
  1838.             Pickind:  begin
  1839.                     SaveInfo := info;
  1840.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1841.                     if not digitizing then begin
  1842.                             UpdatePicWindow;
  1843.                             DrawMyGrowIcon(info^.wptr);
  1844.                         end;
  1845.                     info := SaveInfo;
  1846.                 end;
  1847.             ToolKind: 
  1848.                 DrawTools;
  1849.             MapKind: 
  1850.                 DrawMap;
  1851.             LutKind: 
  1852.                 DrawLUT;
  1853.             InfoKind:  begin
  1854.                     DrawLabels('', '', '');
  1855.                     if (mCount > 0) or (InfoMessage <> '') then
  1856.                         ShowInfo;
  1857.                 end;
  1858.             HistoKind: 
  1859.                 DrawHistogram;
  1860.             ProfilePlotKind, CalibrationPlotKind: 
  1861.                 UpdatePlotWindow;
  1862.             ResultsKind: 
  1863.                 UpdateResultsWindow;
  1864.             PasteControlKind: 
  1865.                 DrawPasteControl;
  1866.             TextKind: 
  1867.                 UpdateTextWindow(WhichWindow);
  1868.         end;
  1869.         EndUpdate(WhichWindow);
  1870.     end;
  1871.  
  1872.  
  1873.     procedure DoDiskInsert (event: EventRecord);
  1874. { Process disk insertion event, check for damaged or uninitialized disks. }
  1875.         var
  1876.             p: point;
  1877.             intjunk: integer;
  1878.     begin
  1879.         if (HiWrd(event.message) <> NoErr) then begin
  1880.                 DiLoad;
  1881.                 SetPt(p, 100, 80);
  1882.                 intjunk := DiBadMount(p, event.message);
  1883.                 DiUnload;
  1884.             end;
  1885.     end;
  1886.  
  1887.  
  1888.     procedure DoDialogEvent (event: EventRecord);
  1889.   {Handles modeless dialog box events}
  1890.         var
  1891.             isItemHit: boolean;
  1892.             theDialog: DialogPtr;
  1893.             ItemHit: integer;
  1894.             ch: char;
  1895.     begin
  1896.         if (Event.what = KeyDown) and (BitAnd(Event.modifiers, CmdKey) = CmdKey) then begin
  1897.                 UpdateMenus;
  1898.                 ch := chr(band(Event.message, CharCodeMask));
  1899.                 DoMenuEvent(MenuKey(ch));
  1900.                 exit(DoDialogEvent);
  1901.             end;
  1902.         isItemHit := DialogSelect(event, theDialog, ItemHit);
  1903.         if isItemHit and (theDialog = VideoControl) then
  1904.             DoVideoControl(ItemHit);
  1905.     end;
  1906.  
  1907.  
  1908.     function MyGotRequiredParams(var theAppleEvent:AppleEvent):OSErr;
  1909.     var
  1910.         err:OSErr;
  1911.         returnedType:DescType;
  1912.         actualSize:Size;
  1913.     begin
  1914.         err:=AEGetAttributePtr(theAppleEvent,
  1915.                     keyMissedKeywordAttr, typeWildCard, returnedType,
  1916.                     nil, 0, actualSize);
  1917.         if err=errAEDescNotFound then
  1918.             myGotRequiredParams:=noErr
  1919.         else  if err=noErr then
  1920.             myGotRequiredParams:=errAEParamMissed;
  1921.     end;
  1922.     
  1923.     
  1924.     procedure PrintDocument;
  1925.     begin
  1926.         UpdatePicWindow;
  1927.         WhatToPrint := PrintImage;
  1928.         Print(false);
  1929.         DoClose;
  1930.     end;
  1931.  
  1932.  
  1933. function OpenFinderFile(myFSS:FSSpec; PrintDoc:boolean):OSErr;
  1934. var
  1935.     theInfo: FInfo;
  1936.     err, err1, err2:OSErr;
  1937.     wdRefNum, f:integer;
  1938.     okay:boolean;
  1939. begin
  1940.     OpenFinderFile:=fnfErr;
  1941.     with myFSS do begin
  1942.         err := OpenWD(VRefNum, parID, 0, wdRefNum);
  1943.         if err<>noErr then
  1944.             exit(OpenFinderFile);
  1945.       err := GetFInfo(name, wdRefNum, theInfo);
  1946.         if err<>noErr then
  1947.             exit(OpenFinderFile);
  1948.         okay:=false;
  1949.         OpeningFinderFiles:=true;
  1950.         if theInfo.fdType = 'TIFF' then begin
  1951.             WhatToOpen := OpenTIFF;
  1952.             okay := OpenFile(name, wdRefNum);
  1953.             if OpeningRGB then begin
  1954.                 if okay then
  1955.                     ConvertRGBToEightBitColor(true);
  1956.                 OpeningRGB := false;
  1957.             end;
  1958.             if PrintDoc then
  1959.                 PrintDocument;
  1960.         end;
  1961.         if theInfo.fdType = 'PICT' then begin
  1962.             okay := OpenPICT(name, wdRefNum, false);
  1963.             if PrintDoc then
  1964.                 PrintDocument;
  1965.         end;
  1966.         if theInfo.fdType = 'TEXT' then begin
  1967.             okay := OpenTextFile(name, wdRefNum);
  1968.         end;
  1969.         if theInfo.fdType = 'PICS' then begin
  1970.             okay := OpenPICS(name, wdRefNum);
  1971.       end;
  1972.         if theInfo.fdType = 'Iout' then begin
  1973.             OpenOutline(name, wdRefNum);
  1974.             okay:=true;
  1975.         end;
  1976.         if theInfo.fdType = 'ICOL' then begin
  1977.             OpenColorTable(name, wdRefNum);
  1978.             okay:=true;
  1979.         end;
  1980.       if theInfo.fdType = 'IPIC' then begin
  1981.             WhatToOpen := OpenImage;
  1982.             okay := OpenFile(name, wdRefNum);
  1983.             if PrintDoc then
  1984.                 PrintDocument;
  1985.         end;
  1986.         if (theInfo.fdType = 'PREF') or (theInfo.fdType = 'pref') then begin
  1987.             err := fsopen(name, wdRefNum, f);
  1988.             GetPreferences(f);
  1989.             if nExtraColors > 0 then
  1990.                 RedrawLUTWindow;
  1991.             if InvertPixelValues then
  1992.                 InvertGrayLevels;
  1993.         end;
  1994.         OpeningFinderFiles:=false;
  1995.         if okay then
  1996.             OpenFinderFile:=noErr;
  1997.   end;
  1998. end;
  1999.  
  2000.  
  2001. function HandleOpenOrPrint(var theAppleEvent, reply:AppleEvent; RefCon:LongInt; PrintDoc:boolean):OSerr;
  2002.     var
  2003.         err, ignoreErr:OSErr;
  2004.         docList:AEDescList;
  2005.         index, ItemsInList:LongInt;
  2006.         actualSize:Size;
  2007.         keywd:AEKeyword;
  2008.         returnedType:DescType;
  2009.         myFSS:FSSpec;
  2010.     begin
  2011.         err:=AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, docList);
  2012.         if err=noErr then begin
  2013.             err:=myGotRequiredParams(theAppleEvent);
  2014.             if err=noErr then begin
  2015.                 err:=AECountItems(docList, itemsInList);
  2016.                 if err=noErr then
  2017.                     for index:=1 to ItemsInList do begin
  2018.                         err:=AEGetNthPtr(docList, index, typeFSS,
  2019.                                         keywd, returnedType, @myFSS,
  2020.                                         SizeOf(myFSS), actualSize);
  2021.                         if err=noErr then begin
  2022.                             err:=OpenFinderFile(myFSS, PrintDoc);
  2023.                         end;
  2024.                     end;
  2025.             end;
  2026.             ignoreErr:=AEDisposeDesc(docList);
  2027.         end;
  2028.         HandleOpenOrPrint:=err;
  2029.     end;
  2030.     
  2031.     
  2032.     function HandleOpenApp(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2033.     begin
  2034.         HandleOpenApp:=noErr;
  2035.     end;
  2036.     
  2037.     
  2038.     function HandleOpenDoc(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2039.     begin
  2040.         HandleOpenDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, false);
  2041.     end;
  2042.  
  2043.  
  2044.     function HandlePrintDoc(var theAppleEvent, reply: AppleEvent; RefCon:LongInt):OSerr;
  2045.     begin
  2046.         HandlePrintDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, true);
  2047.     end;
  2048.     
  2049.     function HandleQuit(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2050.     begin
  2051.         Finished:=true;
  2052.         HandleQuit:=noErr;
  2053.     end;
  2054.  
  2055.  
  2056.     function HandleEvents: boolean;
  2057.         const
  2058.             mousemovedmessage = $FA;
  2059.             SuspendResumeMessage = 1;
  2060.             ResumeMask = 1;
  2061.         var
  2062.             Event: EventRecord;
  2063.             result: boolean;
  2064.             theDialog: DialogPtr;
  2065.             ItemHit: integer;
  2066.             SleepTicks: LongInt;
  2067.             okay: boolean;
  2068.             err:OSErr;
  2069.     begin
  2070.         if Digitizing then
  2071.             SleepTicks := 0
  2072.         else
  2073.             SleepTicks := 2;
  2074.         if WaitNextEvent(EveryEvent, Event, SleepTicks, nil) then begin
  2075.                 if isDialogEvent(event) then
  2076.                     DoDialogEvent(event)
  2077.                 else
  2078.                     case Event.what of
  2079.                         KeyDown, AutoKey: 
  2080.                             DoKeyDown(Event);
  2081.                         MouseDown: 
  2082.                             DoMouseDown(Event);
  2083.                         ActivateEvt: 
  2084.                             DoActivate(Event);
  2085.                         DiskEvt: 
  2086.                             DoDiskInsert(Event);
  2087.                         UpdateEvt: 
  2088.                             DoUpdate(Event);
  2089.                         osEvt: 
  2090.                             case BSR(event.message, 24) of
  2091.                                 MouseMovedMessage: 
  2092.                                     ;
  2093.                                 SuspendResumeMessage: 
  2094.                                     if BAND(event.message, ResumeMask) <> 0 then begin{Resume event}
  2095.                                             if SwitchLUTOnSuspend and (WhatToUndo = UndoLUT) then begin
  2096.                                                     UndoLUTChange;
  2097.                                                     WhatToUndo := NothingToUndo;
  2098.                                                 end
  2099.                                             else
  2100.                                                 LoadLUT(info^.ctable);
  2101.                                         end
  2102.                                     else begin {Suspend event}
  2103.                                             KillOperation;
  2104.                                             ConverToSystemClipboard;
  2105.                                             if SwitchLUTOnSuspend then begin
  2106.                                                     SetupLUTUndo;
  2107.                                                     okay := LoadCLUTResource(AppleDefaultCLUT);
  2108.                                                 end;
  2109.                                         end;
  2110.                             end;
  2111.                         kHighLevelEvent:
  2112.                                 err:=AEProcessAppleEvent (Event);
  2113.                         otherwise {Do nothing}
  2114.                     end; {case}
  2115.                 HandleEvents := true
  2116.             end
  2117.         else
  2118.             HandleEvents := false;
  2119.     end;
  2120.  
  2121.  
  2122.     procedure ShowInsertionPoint;
  2123.         var
  2124.             tRect: rect;
  2125.             Loc: point;
  2126.             height, imag: integer;
  2127.     begin
  2128.         if (not isInsertionPoint) or (info = NoInfo) then
  2129.             exit(ShowInsertionPoint);
  2130.         if CurrentWindow <> PicKind then
  2131.             exit(ShowInsertionPoint);
  2132.         if (TickCount mod (BlinkTime * 2)) < BlinkTime then
  2133.             exit(ShowInsertionPoint);
  2134.         Loc := InsertionPoint;
  2135.         OffscreenToScreen(loc);
  2136.         with info^, tRect do begin
  2137.                 SetPort(wptr);
  2138.                 imag := trunc(magnification + 0.5);
  2139.                 height := CurrentSize * imag;
  2140.                 height := height - height div 4;
  2141.                 left := loc.h;
  2142.                 bottom := loc.v - imag + 1;
  2143.                 top := bottom - height;
  2144.                 right := left + 1;
  2145.                 PenNormal;
  2146.                 PenSize(imag, imag);
  2147.                 PenMode(PatXor);
  2148.                 FrameRect(tRect);
  2149.                 ipTicks := TickCount + 3;
  2150.                 repeat
  2151.                 until TickCount > ipTicks;
  2152.                 FrameRect(tRect);
  2153.             end;
  2154.     end;
  2155.  
  2156.  
  2157.     procedure UndoRoi;
  2158.         var
  2159.             SrcPtr, DstPtr: ptr;
  2160.             offset, ByteCount, tTop, tBottom: LongInt;
  2161.             tRect: rect;
  2162.     begin
  2163.         with info^ do begin
  2164.                 if PixMapSize <> CurrentUndoSize then
  2165.                     exit(UndoRoi);
  2166.                 tRect := RoiRect;
  2167.                 if RoiType = LineRoi then
  2168.                     InsetRect(tRect, -RoiHandleSize, -RoiHandleSize);
  2169.                 with tRect do begin
  2170.                         tTop := top;
  2171.                         tBottom := bottom;
  2172.                         if tTop < 0 then
  2173.                             tTop := 0;
  2174.                         if tTop > PicRect.bottom then
  2175.                             tTop := PicRect.bottom;
  2176.                         if tBottom < 0 then
  2177.                             tBottom := 0;
  2178.                         if tBottom > PicRect.bottom then
  2179.                             tBottom := PicRect.bottom;
  2180.                     end;
  2181.                 offset := tTop * BytesPerRow;
  2182.                 if offset < 0 then
  2183.                     offset := 0;
  2184.                 SrcPtr := ptr(ord4(UndoBuf) + offset);
  2185.                 DstPtr := ptr(ord4(PicBaseAddr) + offset);
  2186.                 ByteCount := (tBottom - tTop) * BytesPerRow;
  2187.                 BlockMove(SrcPtr, DstPtr, ByteCount);
  2188.             end;
  2189.     end;
  2190.  
  2191.  
  2192.     procedure GetLineHandles (var LeftHandle, MiddleHandle, RightHandle: rect);
  2193.         var
  2194.             offset1, offset2, xcenter, ycenter, x1, y1, x2, y2: integer;
  2195.             rx1, ry1, rx2, ry2: extended;
  2196.     begin
  2197.         offset1 := RoiHandleSize div 2;
  2198.         offset2 := offset1 + 1;
  2199.         GetLoi(rx1, ry1, rx2, ry2);
  2200.         x1 := trunc(rx1);
  2201.         y1 := trunc(ry1);
  2202.         x2 := trunc(rx2);
  2203.         y2 := trunc(ry2);
  2204.         SetRect(LeftHandle, x1 - offset1, y1 - offset1, x1 + offset2, y1 + offset2);
  2205.         with info^.RoiRect do begin
  2206.                 xcenter := left + (right - left) div 2;
  2207.                 ycenter := top + (bottom - top) div 2;
  2208.             end;
  2209.         SetRect(MiddleHandle, xcenter - offset1, ycenter - offset1, xcenter + offset2, ycenter + offset2);
  2210.         SetRect(RightHandle, x2 - offset1, y2 - offset1, x2 + offset2, y2 + offset2);
  2211.     end;
  2212.  
  2213.  
  2214.     procedure DrawROI;
  2215.         var
  2216.             tRect: rect;
  2217.             RoiHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2218.             psize: integer;
  2219.             StartTicks: LongInt;
  2220.             SaveGDevice: GDHandle;
  2221.     begin
  2222.         with Info^ do begin
  2223.                 StartTicks := TickCount;
  2224.                 if OpPending then
  2225.                     DoOperation(CurrentOp);
  2226.                 SaveGDevice := GetGDevice;
  2227.                 SetGDevice(osGDevice);
  2228.                 SetPort(GrafPtr(Info^.osPort));
  2229.                 PenNormal;
  2230.                 if ScaleToFitWindow then
  2231.                     if (magnification < 1.0) and (magnification <> 0.0) then begin
  2232.                             psize := round(1.0 / magnification + 1.5);
  2233.                             PenSize(psize, psize);
  2234.                         end;
  2235.                 if not ((MouseState = DownInRoi) and OpPending) then
  2236.                     if PixMapSize <= UndoBufSize then begin
  2237.                             pmForeColor(BlackIndex);
  2238.                             pmBackColor(WhiteIndex);
  2239.                             case RoiType of
  2240.                                 RectRoi: 
  2241.                                     with RoiRect do begin
  2242.                                             SetRect(RoiHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom);
  2243.                                             if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then
  2244.                                                 PaintRect(RoiHandle);
  2245.                                         end;
  2246.                                 LineRoi: 
  2247.                                     if Magnification <= 2.0 then begin
  2248.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2249.                                             PaintRect(LeftHandle);
  2250.                                             if LineWidth < 4 then
  2251.                                                 PaintRect(MiddleHandle);
  2252.                                             PaintRect(RightHandle);
  2253.                                             pmForeColor(WhiteIndex);
  2254.                                             FrameRect(LeftHandle);
  2255.                                             if LineWidth < 4 then
  2256.                                                 FrameRect(MiddleHandle);
  2257.                                             FrameRect(RightHandle);
  2258.                                             pmForeColor(BlackIndex);
  2259.                                         end;
  2260.                                 otherwise
  2261.                             end;
  2262.                             PatIndex := (PatIndex + 1) mod 8;
  2263.                             PenPat(AntPattern[PatIndex]);
  2264.                             FrameRgn(roiRgn);
  2265.                             pmForeColor(ForegroundIndex);
  2266.                             pmBackColor(BackgroundIndex);
  2267.                         end;
  2268.                 if PixMapSize > UndoBufSize then begin
  2269.                         if magnification < 1.0 then
  2270.                             PenSize(2, 2);
  2271.                         PatIndex := (PatIndex + 1) mod 8;
  2272.                         PenPat(AntPattern[PatIndex]);
  2273.                         PenMode(PatXor);
  2274.                         FrameRgn(roiRgn);
  2275.                         if MouseState = DownInRoi then begin
  2276.                                 UnionRect(RoiRect, OldRoiRect, tRect);
  2277.                                 UpdateScreen(tRect);
  2278.                             end
  2279.                         else
  2280.                             UpdateScreen(RoiRect);
  2281.                         FrameRgn(roiRgn);
  2282.                     end
  2283.                 else begin
  2284.                         tRect := RoiRect;
  2285.                         if MouseState = DownInRoi then
  2286.                             UnionRect(RoiRect, OldRoiRect, tRect)
  2287.                         else if RoiNudged then begin
  2288.                                 tRect := RoiRect;
  2289.                                 RoiNudged := false;
  2290.                             end;
  2291.                         if RoiType = LineRoi then
  2292.                             InsetRect(tRect, -RoiHandleSize * 2, -RoiHandleSize * 2)
  2293.                         else
  2294.                             InsetRect(tRect, -2, -2);
  2295.                         UpdateScreen(tRect);
  2296.                         UndoRoi;  {Erase offscreen ROI}
  2297.                     end;
  2298.                 RoiUpdateTime := TickCount - StartTicks;
  2299.             end; {with}
  2300.         SetGDevice(SaveGDevice);
  2301.     end;
  2302.  
  2303.  
  2304.     procedure MoveLineEndPoint (osloc: point);
  2305.         var
  2306.             deltax, deltay: extended;
  2307.     begin
  2308.         with info^, osloc, info^.RoiRect do begin
  2309.                 if h < 0 then
  2310.                     h := 0;
  2311.                 if h > PicRect.right then
  2312.                     h := PicRect.right;
  2313.                 if v < 0 then
  2314.                     v := 0;
  2315.                 if v > PicRect.bottom then
  2316.                     v := PicRect.bottom;
  2317.                 if RoiMode = LeftEndMode then begin
  2318.                         LX1 := h;
  2319.                         LY1 := v;
  2320.                         LX2 := left + LX2;
  2321.                         LY2 := top + LY2;
  2322.                     end
  2323.                 else begin
  2324.                         LX2 := h;
  2325.                         LY2 := v;
  2326.                         LX1 := left + LX1;
  2327.                         LY1 := top + LY1;
  2328.                     end;
  2329.                 if ShiftKeyDown then begin
  2330.                         deltax := LX2 - LX1;
  2331.                         deltay := LY2 - LY1;
  2332.                         if abs(deltax) > abs(deltay) then begin
  2333.                                 if RoiMode = LeftEndMode then
  2334.                                     LY2 := LY1
  2335.                                 else
  2336.                                     LY1 := LY2
  2337.                             end
  2338.                         else begin
  2339.                                 if RoiMode = LeftEndMode then
  2340.                                     LX2 := LX1
  2341.                                 else
  2342.                                     LX1 := LX2
  2343.                             end;
  2344.                     end; {if ShiftKeyDown}
  2345.                 MakeRegion;
  2346.                 osMouseDownLoc := osloc;
  2347.                 RoiUpdateTime := 0;
  2348.                 Show3Values(h, v, MyGetPixel(h, v));
  2349.             end;
  2350.     end;
  2351.  
  2352.  
  2353.     procedure MoveRoi (osloc: point);
  2354.         var
  2355.             dh, dv: integer;
  2356.     begin
  2357.         with info^, info^.RoiRect, osloc do begin
  2358.                 dh := h - osMouseDownLoc.h;
  2359.                 dv := v - osMouseDownLoc.v;
  2360.                 OldRoiRect := RoiRect;
  2361.                 if RoiType = LineRoi then
  2362.                     if (RoiMode = LeftEndMode) or (RoiMode = RightEndMode) then begin
  2363.                             MoveLineEndPoint(osloc);
  2364.                             exit(MoveRoi);
  2365.                         end;
  2366.                 if RoiMode = MoveMode then begin
  2367.                         if RoiMovementState = Constrained then begin
  2368.                                 if dv <> 0 then
  2369.                                     RoiMovementState := ConstrainedV
  2370.                                 else if dh <> 0 then
  2371.                                     RoiMovementState := ConstrainedH
  2372.                             end;
  2373.                         if RoiMovementState = ConstrainedH then
  2374.                             dv := 0
  2375.                         else if RoiMovementState = ConstrainedV then
  2376.                             dh := 0;
  2377.                         if not OpPending then begin
  2378.                                 if left + dh < 0 then
  2379.                                     dh := -left;
  2380.                                 if top + dv < 0 then
  2381.                                     dv := -top;
  2382.                             end;
  2383.                     end;
  2384.                 if not OpPending then begin
  2385.                         if right + dh > PicRect.right then
  2386.                             dh := PicRect.right - right;
  2387.                         if bottom + dv > PicRect.bottom then
  2388.                             dv := PicRect.bottom - bottom;
  2389.                     end;
  2390.                 if RoiMode = StretchMode then begin
  2391.                         measuring := false;
  2392.                         DrawLabels('Width:', 'Height:', '');
  2393.                         if h > left then begin
  2394.                                 right := right + dh;
  2395.                                 if right < (left + 1) then
  2396.                                     right := left + 1;
  2397.                                 if (right - h) > 5 then
  2398.                                     right := h + 2;
  2399.                             end
  2400.                         else
  2401.                             right := left + 1;
  2402.                         if v > top then begin
  2403.                                 bottom := bottom + dv;
  2404.                                 if bottom < (top + 1) then
  2405.                                     bottom := top + 1;
  2406.                                 if (bottom - v) > 5 then
  2407.                                     bottom := v + 2;
  2408.                             end
  2409.                         else
  2410.                             bottom := top + 1;
  2411.                         Show3Values(right - left, bottom - top, -1);
  2412.                         MakeRegion;
  2413.                     end
  2414.                 else begin
  2415.                         OffsetRgn(roiRgn, dh, dv);
  2416.                         Show3Values(left, top, MyGetPixel(left, top));
  2417.                     end;
  2418.                 RoiRect := roiRgn^^.rgnBBox;
  2419.                 osMouseDownLoc := osloc;
  2420.                 RoiUpdateTime := 0; {Forces ROI outline to be redrawn}
  2421.             end; {with Info}
  2422.     end;
  2423.  
  2424.  
  2425.     procedure ShowHistogramValues (GrayLevel: LongInt);
  2426.         var
  2427.             hstart, vstart, ivalue: integer;
  2428.     begin
  2429.         hstart := InfoHStart;
  2430.         vstart := InfoVStart;
  2431.         SetPort(InfoWindow);
  2432.         TextSize(9);
  2433.         TextFont(Monaco);
  2434.         TextMode(SrcCopy);
  2435.         MoveTo(xValueLoc, vstart);
  2436.         with info^ do
  2437.             if fit = uncalibrated then
  2438.                 DrawLong(GrayLevel)
  2439.             else begin
  2440.                     if InvertingCalibrationFunction then
  2441.                         DrawReal(cvalue[255 - GrayLevel], 8, 2)
  2442.                     else
  2443.                         DrawReal(cvalue[GrayLevel], 8, 2);
  2444.                     DrawString(' (');
  2445.                     DrawLong(GrayLevel);
  2446.                     DrawString(' )');
  2447.                 end;
  2448.         DrawString('          ');
  2449.         MoveTo(yValueLoc, vstart + 10);
  2450.         if InvertingCalibrationFunction then
  2451.             DrawLong(histogram[255 - GrayLevel])
  2452.         else
  2453.             DrawLong(histogram[GrayLevel]);
  2454.         DrawString('          ');
  2455.     end;
  2456.  
  2457.  
  2458.     procedure DoPlotCursor (loc: point; kind: integer);
  2459.         var
  2460.             xxscale, angle: extended;
  2461.             xvalue, xinc, yinc: integer;
  2462.             pt: point;
  2463.     begin
  2464.         DrawLabels('X:', 'Y:', '');
  2465.         SetCursor(ToolCursor[SelectionTool]);
  2466.         SetPort(PlotWindow);
  2467.         GlobalToLocal(loc);
  2468.         xxscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin);
  2469.         xvalue := trunc((loc.h - PlotLeftMargin) * xxscale);
  2470.         if (xvalue < 0) or (xvalue >= PlotCount) then
  2471.             exit(DoPlotCursor);
  2472.         Show2PlotValues(xvalue, PlotData^[xvalue]);
  2473.         if (kind = CalibrationPlotKind) or (info^.RoiType <> LineRoi) then
  2474.             exit(DoPlotCursor);
  2475.         if button and (info <> NoInfo) then
  2476.             with loc do begin
  2477.                     SetPort(info^.wptr);
  2478.                     PenMode(PatXor);
  2479.                     PenSize(1, 1);
  2480.                     angle := (PlotAngle / 180.0) * pi;
  2481.                     xinc := round(cos(angle) * xvalue);
  2482.                     yinc := round(-sin(angle) * xvalue);
  2483.                     h := PlotStart.h + xinc;
  2484.                     v := PlotStart.v + yinc;
  2485.                     OffscreenToScreen(loc);
  2486.                     MoveTo(h - 7, v);
  2487.                     LineTo(h + 7, v);
  2488.                     MoveTo(h, v - 7);
  2489.                     LineTo(h, v + 7);
  2490.                     wait(2);
  2491.                     MoveTo(h - 7, v);
  2492.                     LineTo(h + 7, v);
  2493.                     MoveTo(h, v - 7);
  2494.                     LineTo(h, v + 7);
  2495.                 end;
  2496.     end;
  2497.  
  2498.  
  2499.     procedure SelectCursor;
  2500.         var
  2501.             loc, osloc, gloc: point;
  2502.             where, kind, i, color, x, y, margin: integer;
  2503.             WhichWindow: WindowPtr;
  2504.             MouseInRoi: boolean;
  2505.             fwptr: WindowPtr;
  2506.             CalValue: extended;
  2507.             RoiStretchHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2508.             MovingRoi: boolean;
  2509.             pvalue: integer;
  2510.     begin
  2511.         if PasteControl <> nil then begin
  2512.                 fwptr := FrontWindow;
  2513.                 if fwptr <> nil then
  2514.                     if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then
  2515.                         BringToFront(PasteControl);
  2516.             end;
  2517.         SetPort(ScreenPort);
  2518.         GetMouse(gloc);
  2519.         loc := gloc;
  2520.         where := FindWindow(gloc, WhichWindow);
  2521.         if WhichWindow = nil then begin
  2522.                 InitCursor;
  2523.                 exit(SelectCursor)
  2524.             end;
  2525.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2526.         if kind < 0 then
  2527.             exit(SelectCursor); {System Window}
  2528.         if where <> InContent then begin
  2529.                 InitCursor;
  2530.                 exit(SelectCursor)
  2531.             end;
  2532.         case kind of
  2533.             PicKind:  begin
  2534.                     if Info = NoInfo then begin
  2535.                             InitCursor;
  2536.                             exit(SelectCursor)
  2537.                         end;
  2538.                     SetPort(info^.wptr);
  2539.                     GlobalToLocal(loc);
  2540.                     osloc := loc;
  2541.                     ScreenToOffscreen(osloc);
  2542.                     MovingRoi := false;
  2543.                     with info^ do begin
  2544.                             SelectionMode := NewSelection;
  2545.                             if RoiShowing and ((isSelectionTool) or (CurrentTool = Wand)) and (currentTool <> LineTool) then begin
  2546.                                     if OptionKeyDown then
  2547.                                         SelectionMode := SubSelection
  2548.                                     else if ControlKeyDown or (ShiftKeyDown and (CurrentTool <> OvalSelectionTool) and (CurrentTool <> SelectionTool)) then
  2549.                                         SelectionMode := AddSelection;
  2550.                                 end;
  2551.                             if RoiShowing and (SelectionMode = NewSelection) then begin
  2552.                                     MouseInRoi := PtInRgn(osloc, roiRgn);
  2553.                                     if RoiType = LineRoi then begin
  2554.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2555.                                             if magnification <= 2.0 then begin
  2556.                                                     InsetRect(LeftHandle, -2, -2);
  2557.                                                     InsetRect(MiddleHandle, -2, -2);
  2558.                                                     InsetRect(RightHandle, -2, -2);
  2559.                                                 end;
  2560.                                             MouseInRoi := MouseInRoi or PtInRect(osloc, LeftHandle) or MouseInRoi or PtInRect(osloc, MiddleHandle) or MouseInRoi or PtInRect(osloc, RightHandle);
  2561.                                         end;
  2562.                                 end
  2563.                             else
  2564.                                 MouseInRoi := false
  2565.                         end; {with}
  2566.                     if MouseInRoi or (MouseState = DownInRoi) then begin
  2567.                             if MouseState = NotInRoi then
  2568.                                 MouseState := InRoi;
  2569.                             InitCursor;
  2570.                             if button then begin
  2571.                                     if MouseState = InRoi then begin
  2572.                                             if OpPending and (CurrentOp <> PasteOp) then
  2573.                                                 SetupUndo;
  2574.                                             MouseState := DownInRoi;
  2575.                                             osMouseDownLoc := osloc;
  2576.                                             with info^ do
  2577.                                                 case RoiType of
  2578.                                                     RectRoi:  begin
  2579.                                                             if magnification > 1.0 then
  2580.                                                                 margin := 0
  2581.                                                             else
  2582.                                                                 margin := 2;
  2583.                                                             with RoiRect do
  2584.                                                                 SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom);
  2585.                                                             if PtInRect(osloc, RoiStretchHandle) then
  2586.                                                                 RoiMode := StretchMode
  2587.                                                             else
  2588.                                                                 RoiMode := MoveMode;
  2589.                                                         end;
  2590.                                                     LineRoi: 
  2591.                                                         if PtInRect(osloc, LeftHandle) then
  2592.                                                             RoiMode := LeftEndMode
  2593.                                                         else if PtInRect(osloc, RightHandle) then
  2594.                                                             RoiMode := RightEndMode
  2595.                                                         else
  2596.                                                             RoiMode := MoveMode;
  2597.                                                     otherwise
  2598.                                                 end; {case}
  2599.                                             if ShiftKeyDown then
  2600.                                                 RoiMovementState := Constrained
  2601.                                             else
  2602.                                                 RoiMovementState := Unconstrained;
  2603.                                         end;
  2604.                                     MoveRoi(osloc);
  2605.                                     MovingRoi := true;
  2606.                                 end
  2607.                             else
  2608.                                 MouseState := InRoi
  2609.                         end
  2610.                     else begin
  2611.                             MouseState := NotInRoi;
  2612.                             if SpaceBarDown and (CurrentTool <> TextTool) then
  2613.                                 SetCursor(ToolCursor[Grabber])
  2614.                             else if (SelectionMode = AddSelection) and (CurrentTool = Wand) then
  2615.                                 SetCursor(WandPlusCursor)
  2616.                             else if (SelectionMode = SubSelection) and (CurrentTool = Wand) then
  2617.                                 SetCursor(WandMinusCursor)
  2618.                             else if SelectionMode = AddSelection then
  2619.                                 SetCursor(CrossPlusCursor)
  2620.                             else if SelectionMode = SubSelection then
  2621.                                 SetCursor(CrossMinusCursor)
  2622.                             else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then
  2623.                                 SetCursor(GlassMinusCursor)
  2624.                             else
  2625.                                 SetCursor(ToolCursor[CurrentTool]);
  2626.                         end;
  2627.                     if not MovingRoi then begin
  2628.                             if isFFT then begin
  2629.                                     DrawLabels('r:', 'theta:', 'Value:');
  2630.                                     with osloc do
  2631.                                         ShowFFTValues(h, v, MyGetPixel(h, v));
  2632.                                     exit(SelectCursor);
  2633.                                 end;
  2634.                             if CurrentTool = PickerTool then
  2635.                                 DrawLabels('X:', 'Y:', 'RGB:')
  2636.                             else
  2637.                                 DrawLabels('X:', 'Y:', 'Value:');
  2638.                             with osloc do begin
  2639.                                     if Digitizing then
  2640.                                         pvalue := GetFGPixel(h, v)
  2641.                                     else
  2642.                                         pvalue := MyGetPixel(h, v);
  2643.                                     Show3Values(h, v, pvalue);
  2644.                                 end;
  2645.                         end;
  2646.                 end;
  2647.             HistoKind:  begin
  2648.                     DrawLabels('Level:', 'Count:', '');
  2649.                     SetCursor(ToolCursor[SelectionTool]);
  2650.                     SetPort(HistoWindow);
  2651.                     GlobalToLocal(loc);
  2652.                     ShowHistogramValues(loc.h);
  2653.                 end;
  2654.             ProfilePlotKind, CalibrationPlotKind: 
  2655.                 DoPlotCursor(loc, kind);
  2656.             LUTKind:  begin
  2657.                     if info^.fit <> uncalibrated then
  2658.                         DrawLabels('Index:', 'Value:', '  RGB:')
  2659.                     else
  2660.                         DrawLabels('Index:', '  RGB:', '');
  2661.                     SetPort(LUTWindow);
  2662.                     GlobalToLocal(loc);
  2663.                     if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  2664.                             if loc.v < 256 then
  2665.                                 SetCursor(LUTCursor)
  2666.                             else
  2667.                                 InitCursor
  2668.                         end
  2669.                     else
  2670.                         SetCursor(PickerCursor);
  2671.                     if loc.v < 256 then begin
  2672.                             ShowRGBValues(loc.v);
  2673.                         end
  2674.                     else begin
  2675.                             color := 0;
  2676.                             for i := 1 to nExtraColors + 2 do
  2677.                                 if PtInRect(loc, ExtraColorsRect[i]) then
  2678.                                     Color := ExtraColorsEntry[i];
  2679.                             ShowRGBValues(color);
  2680.                         end;
  2681.                 end;
  2682.             MapKind: 
  2683.                 if OptionKeyDown then
  2684.                     SetCursor(ToolCursor[SelectionTool])
  2685.                 else
  2686.                     SetCursor(gmCursor);
  2687.             TextKind:  begin
  2688.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  2689.                     if TextInfo <> nil then
  2690.                         with TextInfo^ do begin
  2691.                                 SetPort(TextWindowPtr);
  2692.                                 GlobalToLocal(loc);
  2693.                                 TEIdle(TextTE);
  2694.                                 with TextWindowPtr^.portRect do begin
  2695.                                         if (loc.h < (right - ScrollBarWidth)) and (loc.v < (bottom - ScrollBarWidth)) then
  2696.                                             SetCursor(ToolCursor[TextTool])
  2697.                                         else
  2698.                                             InitCursor;
  2699.                                     end;
  2700.                             end;
  2701.                 end;
  2702.             otherwise
  2703.                 InitCursor;
  2704.         end; {case}
  2705.     end;
  2706.  
  2707.  
  2708.     procedure CloseAll;
  2709.         var
  2710.             i, j, result: integer;
  2711.             WPeek, NextWPeek: WindowPeek;
  2712.             ignore: boolean;
  2713.     begin
  2714.         InitCursor;
  2715.         WPeek := WindowPeek(FrontWindow);
  2716.         StopDigitizing;
  2717.         while wpeek <> nil do begin
  2718.                 NextWPeek := WPeek^.NextWindow;
  2719.                 case wPeek^.WindowKind of
  2720.                     PicKind:  begin
  2721.                             Info := pointer(WPeek^.RefCon);
  2722.                             result := CloseAWindow(info^.wptr);
  2723.                             if not CommandPeriod then
  2724.                                 for j := 1 to 2 do
  2725.                                     ignore := HandleEvents;
  2726.                             if result = cancel then begin
  2727.                                     ActivateWindow;
  2728.                                     finished := false;
  2729.                                     exit(CloseAll)
  2730.                                 end;
  2731.                         end;
  2732.                     TextKind:  begin
  2733.                             result := CloseAWindow(WindowPtr(wPeek));
  2734.                             if result = cancel then begin
  2735.                                     finished := false;
  2736.                                     exit(CloseAll)
  2737.                                 end;
  2738.                         end;
  2739.                     otherwise
  2740.                         ;
  2741.                 end; {case}
  2742.                 wpeek := NextWPeek;
  2743.             end;
  2744.     end;
  2745.  
  2746.  
  2747.  
  2748.  
  2749.     procedure LoadDefaultMacros;
  2750.   {Looks for a text file named "Image Macros" in the same folder as}
  2751.   {Image, and, if found,  loads the macros contained in it.}
  2752.         var
  2753.             err: OSErr;
  2754.             LaunchRefNum: integer;
  2755.             FinderInfo: FInfo;
  2756.             id: LongInt;
  2757.     begin
  2758.         err := GetVol(nil, LaunchRefNum);
  2759.         if err = noerr then
  2760.             err := GetFInfo('Image Macros', LaunchRefNum, FinderInfo);
  2761.         if err = NoErr then begin
  2762.                 LoadMacrosFromFile('Image Macros', LaunchRefNum);
  2763.                 {$ifc not PowerPC}
  2764.                     UnloadSeg(@LoadMacros);
  2765.                 {$endc}
  2766.             end;
  2767.     end;
  2768.  
  2769.  
  2770.     procedure Shutdown;
  2771.         var
  2772.             AlertID: integer;
  2773.     begin
  2774.         if (UnsavedResults and (mCount > 10)) or (UnsavedResults and (ResultsWindow <> nil)) then begin
  2775.                 InitCursor;
  2776.                 AlertID := alert(500, nil);
  2777.                 if AlertID = CancelResetID then begin
  2778.                         finished := false;
  2779.                         exit(Shutdown)
  2780.                     end;
  2781.             end;
  2782.         CloseAll;
  2783.         if finished then
  2784.             ConverToSystemClipboard;
  2785.     end;
  2786.  
  2787.  
  2788.     procedure InstallEventHandlers;
  2789.     {Installs event handlers for the four required Apple Events.}
  2790.     var
  2791.         err:OSErr;
  2792.     begin
  2793.         err:=AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(@HandleOpenApp), 0, false);
  2794.         err:=AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(@HandleOpendoc), 0, false);
  2795.         err:=AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(@HandlePrintDoc), 0, false);
  2796.         err:=AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(@HandleQuit), 0, false);
  2797.     end;
  2798.  
  2799.  
  2800. begin
  2801.     Init;
  2802.     InstallEventHandlers;
  2803.     SetupMenus;
  2804.     {GetSettings moved to Init}
  2805.     AllocateBuffers;
  2806.     AllocateArrays;
  2807.     ConvertFromSystemClipboard;
  2808.     LoadDefaultMacros;
  2809.     FindPlugIns;
  2810.     {$ifc not PowerPC}
  2811.         UnloadSeg(@Init);
  2812.     {$endc}
  2813.   {InitUser;}
  2814.     repeat
  2815.         if not HandleEvents then
  2816.             if info^.RoiShowing and (RoiUpdateTime < 30) then
  2817.                 DrawRoi;
  2818.         ShowInsertionPoint;
  2819.         SelectCursor;
  2820.         if Digitizing then begin
  2821.                 CaptureAndDisplayFrame;
  2822.                 if ContinuousHistogram then
  2823.                     ShowContinuousHistogram;
  2824.             end;
  2825.         if Finished then
  2826.             Shutdown;
  2827.     until finished;
  2828.     CloseSerialPorts;
  2829.     isOK := LoadCLUTResource(AppleDefaultCLUT);
  2830.     RestoreScreen; {Force Finder to redraw color icons}
  2831. end.